How to map Java's locales and Lucene's analyzers? - java

I would like to find the Lucene analyzer corresponding to the language of a Java locale.
For instance, Locale.ENGLISH would be mapped to org.apache.lucene.analysis.en.EnglishAnalyzer.
Is there an automated mapping somewhere?

This is not available out-of-the-box. See below the way I do it.
public final class LocaleAwareAnalyzer extends AnalyzerWrapper {
private static final Logger LOG = LoggerFactory.getLogger(LocaleAwareAnalyzer.class);
private final Analyzer defaultAnalyzer;
private final Map<String, Analyzer> perLocaleAnalyzer = perLocaleAnalyzers();
public LocaleAwareAnalyzer(final Analyzer defaultAnalyzer) {
this.defaultAnalyzer = Precondition.notNull("defaultAnalyzer", defaultAnalyzer);
}
#Override
protected Analyzer getWrappedAnalyzer(final String fieldName) {
if (fieldName == null) {
return defaultAnalyzer;
}
final int n = fieldName.indexOf('_');
if (n >= 0) {
// Unfortunately CharArrayMap does not offer get(CharSequence, start, end)
final String locale = fieldName.substring(n + 1);
final Analyzer a = perLocaleAnalyzer.get(locale);
if (a != null) {
return a;
}
LOG.warn("No Analyzer for Locale '%s', using default", locale);
}
return defaultAnalyzer;
}
#Override
protected TokenStreamComponents wrapComponents(final String fieldName,
final TokenStreamComponents components) {
return components;
}
private static Map<String, Analyzer> perLocaleAnalyzers() {
final Map<String, Analyzer> m = new HashMap<>();
m.put("en", new EnglishAnalyzer(Version.LUCENE_43));
m.put("es", new SpanishAnalyzer(Version.LUCENE_43));
m.put("de", new GermanAnalyzer(Version.LUCENE_43));
m.put("fr", new FrenchAnalyzer(Version.LUCENE_43));
// ... etc
return m;
}
}

Related

How to sort by querydsl alias

Is there a way to sort repository query results by querydsl alias?
So far I've managed to filter, but sorting results with an error:
org.springframework.data.mapping.PropertyReferenceException: No property username found for type User!
request:
GET /users?size=1&sort=username,desc
my rest controller method:
#GetMapping("/users")
public ListResult<User> getUsersInGroup(
#ApiIgnore #QuerydslPredicate(root = User.class) Predicate predicate,
Pageable pageable) {
Page<User> usersInGroup =
userRepository.findByGroup(CurrentUser.getGroup(), predicate, pageable);
return new ListResult<>(usersInGroup);
}
my repository:
#Override
default void customize(QuerydslBindings bindings, QUser root) {
bindings.including(root.account.login, root.account.firstName, root.account.lastName,
root.account.phoneNumber, root.account.email, root.account.postalCode, root.account.city,
root.account.address, root.account.language, root.account.presentationAlias);
bindAlias(bindings, root.account.login, "username");
}
default Page<User> findByGroup(Group group, Predicate predicate, Pageable pageable) {
BooleanExpression byGroup = QUser.user.group.eq(group);
BooleanExpression finalPredicate = byGroup.and(predicate);
return findAll(finalPredicate, pageable);
}
default void bindAlias(QuerydslBindings bindings, StringPath path, String alias) {
bindings.bind(path).as(alias).first(StringExpression::likeIgnoreCase);
}
I've also tried to implement my own PageableArgumentResolver based on QuerydslPredicateArgumentResolver, but some of the methods used there are package private so I thought maybe I am going in the wrong direction
I succeeded by creating a PageableArgumentResolver annotated with class type of query root class and adding alias registry to my generic repository interface.
This solution seems like a workaround but at least it works ;)
repository:
public interface UserRepository extends PageableAndFilterableGenericRepository<User, QUser> {
QDSLAliasRegistry aliasRegistry = QDSLAliasRegistry.instance();
#Override
default void customize(QuerydslBindings bindings, QUser root) {
bindAlias(bindings, root.account.login, "username");
}
default void bindAlias(QuerydslBindings bindings, StringPath path, String alias) {
bindings.bind(path).as(alias).first(StringExpression::likeIgnoreCase);
aliasRegistry.register(alias, path);
}
alias registry:
public class QDSLAliasRegistry {
private static QDSLAliasRegistry inst;
public static QDSLAliasRegistry instance() {
inst = inst == null ? new QDSLAliasRegistry() : inst;
return inst;
}
private QDSLAliasRegistry() {
registry = HashBiMap.create();
}
HashBiMap<String, Path<?>> registry;
resolver:
public class QDSLSafePageResolver implements PageableArgumentResolver {
private static final String DEFAULT_PAGE = "0";
private static final String DEFAULT_PAGE_SIZE = "20";
private static final String PAGE_PARAM = "page";
private static final String SIZE_PARAM = "size";
private static final String SORT_PARAM = "sort";
private final QDSLAliasRegistry aliasRegistry;
public QDSLSafePageResolver(QDSLAliasRegistry aliasRegistry) {
this.aliasRegistry = aliasRegistry;
}
#Override
public boolean supportsParameter(MethodParameter parameter) {
return Pageable.class.equals(parameter.getParameterType())
&& parameter.hasParameterAnnotation(QDSLPageable.class);
}
#Override
public Pageable resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
MultiValueMap<String, String> parameterMap = getParameterMap(webRequest);
final Class<?> root = parameter.getParameterAnnotation(QDSLPageable.class).root();
final ClassTypeInformation<?> typeInformation = ClassTypeInformation.from(root);
String pageStr = Optional.ofNullable(parameterMap.getFirst(PAGE_PARAM)).orElse(DEFAULT_PAGE);
String sizeStr = Optional.ofNullable(parameterMap.getFirst(SIZE_PARAM)).orElse(DEFAULT_PAGE_SIZE);
int page = Integer.parseInt(pageStr);
int size = Integer.parseInt(sizeStr);
List<String> sortStrings = parameterMap.get(SORT_PARAM);
if(sortStrings != null) {
OrderSpecifier[] specifiers = new OrderSpecifier[sortStrings.size()];
for(int i = 0; i < sortStrings.size(); i++) {
String sort = sortStrings.get(i);
String[] orderArr = sort.split(",");
Order order = orderArr.length == 1 ? Order.ASC : Order.valueOf(orderArr[1].toUpperCase());
specifiers[i] = buildOrderSpecifier(orderArr[0], order, typeInformation);
}
return new QPageRequest(page, size, specifiers);
} else {
return new QPageRequest(page, size);
}
}
private MultiValueMap<String, String> getParameterMap(NativeWebRequest webRequest) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
for (Map.Entry<String, String[]> entry : webRequest.getParameterMap().entrySet()) {
parameters.put(entry.getKey(), Arrays.asList(entry.getValue()));
}
return parameters;
}
private OrderSpecifier<?> buildOrderSpecifier(String sort,
Order order,
ClassTypeInformation<?> typeInfo) {
Expression<?> sortPropertyExpression = new PathBuilderFactory().create(typeInfo.getType());
String dotPath = aliasRegistry.getDotPath(sort);
PropertyPath path = PropertyPath.from(dotPath, typeInfo);
sortPropertyExpression = Expressions.path(path.getType(), (Path<?>) sortPropertyExpression, path.toDotPath());
return new OrderSpecifier(order, sortPropertyExpression);
}
}

Best way to handle huge fields with GSON JsonReader

I'm getting a java.lang.OutOfMemoryError: Java heap space even with GSON Streaming.
{"result":"OK","base64":"JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC...."}
base64 can be up to 200Mb long. GSON is taking much more memory than that, (3GB) When I try to store the base64 in a variable I get a:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:535)
at java.lang.StringBuilder.append(StringBuilder.java:204)
at com.google.gson.stream.JsonReader.nextQuotedValue(JsonReader.java:1014)
at com.google.gson.stream.JsonReader.nextString(JsonReader.java:815)
What is the best way to handle this kind of fields?
The reason of why you're getting OutOfMemoryError is that GSON nextString() returns a string that's aggregated during building a very huge string using StringBuilder. When you're facing with such an issue, you have to deal with intermediate data since there is no other choice. Unfortunately, GSON does not let you to process huge literals in any way.
Not sure if you can change the response payload, but if you can't, you might want to implement your own JSON reader, or "hack" the existing JsonReader to make it work in streaming fashion. The example below is based on GSON 2.5 and makes heavy use of reflection because JsonReader hides its state very carefully.
EnhancedGson25JsonReader.java
final class EnhancedGson25JsonReader
extends JsonReader {
// A listener to accept the internal character buffers.
// Accepting a single string built on such buffers is total memory waste as well.
interface ISlicedStringListener {
void accept(char[] buffer, int start, int length)
throws IOException;
}
// The constants can be just copied
/** #see JsonReader#PEEKED_NONE */
private static final int PEEKED_NONE = 0;
/** #see JsonReader#PEEKED_SINGLE_QUOTED */
private static final int PEEKED_SINGLE_QUOTED = 8;
/** #see JsonReader#PEEKED_DOUBLE_QUOTED */
private static final int PEEKED_DOUBLE_QUOTED = 9;
// Here is a bunch of spies made to "spy" for the parent's class state
private final FieldSpy<Integer> peeked;
private final MethodSpy<Integer> doPeek;
private final MethodSpy<Integer> getLineNumber;
private final MethodSpy<Integer> getColumnNumber;
private final FieldSpy<char[]> buffer;
private final FieldSpy<Integer> pos;
private final FieldSpy<Integer> limit;
private final MethodSpy<Character> readEscapeCharacter;
private final FieldSpy<Integer> lineNumber;
private final FieldSpy<Integer> lineStart;
private final MethodSpy<Boolean> fillBuffer;
private final MethodSpy<IOException> syntaxError;
private final FieldSpy<Integer> stackSize;
private final FieldSpy<int[]> pathIndices;
private EnhancedJsonReader(final Reader reader)
throws NoSuchFieldException, NoSuchMethodException {
super(reader);
peeked = spyField(JsonReader.class, this, "peeked");
doPeek = spyMethod(JsonReader.class, this, "doPeek");
getLineNumber = spyMethod(JsonReader.class, this, "getLineNumber");
getColumnNumber = spyMethod(JsonReader.class, this, "getColumnNumber");
buffer = spyField(JsonReader.class, this, "buffer");
pos = spyField(JsonReader.class, this, "pos");
limit = spyField(JsonReader.class, this, "limit");
readEscapeCharacter = spyMethod(JsonReader.class, this, "readEscapeCharacter");
lineNumber = spyField(JsonReader.class, this, "lineNumber");
lineStart = spyField(JsonReader.class, this, "lineStart");
fillBuffer = spyMethod(JsonReader.class, this, "fillBuffer", int.class);
syntaxError = spyMethod(JsonReader.class, this, "syntaxError", String.class);
stackSize = spyField(JsonReader.class, this, "stackSize");
pathIndices = spyField(JsonReader.class, this, "pathIndices");
}
static EnhancedJsonReader getEnhancedGson25JsonReader(final Reader reader) {
try {
return new EnhancedJsonReader(reader);
} catch ( final NoSuchFieldException | NoSuchMethodException ex ) {
throw new RuntimeException(ex);
}
}
// This method has been copied and reworked from the nextString() implementation
void nextSlicedString(final ISlicedStringListener listener)
throws IOException {
int p = peeked.get();
if ( p == PEEKED_NONE ) {
p = doPeek.get();
}
switch ( p ) {
case PEEKED_SINGLE_QUOTED:
nextQuotedSlicedValue('\'', listener);
break;
case PEEKED_DOUBLE_QUOTED:
nextQuotedSlicedValue('"', listener);
break;
default:
throw new IllegalStateException("Expected a string but was " + peek()
+ " at line " + getLineNumber.get()
+ " column " + getColumnNumber.get()
+ " path " + getPath()
);
}
peeked.accept(PEEKED_NONE);
pathIndices.get()[stackSize.get() - 1]++;
}
// The following method is also a copy-paste that was patched for the "spies".
// It's, in principle, the same as the source one, but it has one more buffer singleCharBuffer
// in order not to add another method to the ISlicedStringListener interface (enjoy lamdbas as much as possible).
// Note that the main difference between these two methods is that this one
// does not aggregate a single string value, but just delegates the internal
// buffers to call-sites, so the latter ones might do anything with the buffers.
/**
* #see JsonReader#nextQuotedValue(char)
*/
private void nextQuotedSlicedValue(final char quote, final ISlicedStringListener listener)
throws IOException {
final char[] buffer = this.buffer.get();
final char[] singleCharBuffer = new char[1];
while ( true ) {
int p = pos.get();
int l = limit.get();
int start = p;
while ( p < l ) {
final int c = buffer[p++];
if ( c == quote ) {
pos.accept(p);
listener.accept(buffer, start, p - start - 1);
return;
} else if ( c == '\\' ) {
pos.accept(p);
listener.accept(buffer, start, p - start - 1);
singleCharBuffer[0] = readEscapeCharacter.get();
listener.accept(singleCharBuffer, 0, 1);
p = pos.get();
l = limit.get();
start = p;
} else if ( c == '\n' ) {
lineNumber.accept(lineNumber.get() + 1);
lineStart.accept(p);
}
}
listener.accept(buffer, start, p - start);
pos.accept(p);
if ( !fillBuffer.apply(just1) ) {
throw syntaxError.apply(justUnterminatedString);
}
}
}
// Save some memory
private static final Object[] just1 = { 1 };
private static final Object[] justUnterminatedString = { "Unterminated string" };
}
FieldSpy.java
final class FieldSpy<T>
implements Supplier<T>, Consumer<T> {
private final Object instance;
private final Field field;
private FieldSpy(final Object instance, final Field field) {
this.instance = instance;
this.field = field;
}
static <T> FieldSpy<T> spyField(final Class<?> declaringClass, final Object instance, final String fieldName)
throws NoSuchFieldException {
final Field field = declaringClass.getDeclaredField(fieldName);
field.setAccessible(true);
return new FieldSpy<>(instance, field);
}
#Override
public T get() {
try {
#SuppressWarnings("unchecked")
final T value = (T) field.get(instance);
return value;
} catch ( final IllegalAccessException ex ) {
throw new RuntimeException(ex);
}
}
#Override
public void accept(final T value) {
try {
field.set(instance, value);
} catch ( final IllegalAccessException ex ) {
throw new RuntimeException(ex);
}
}
}
MethodSpy.java
final class MethodSpy<T>
implements Function<Object[], T>, Supplier<T> {
private static final Object[] emptyObjectArray = {};
private final Object instance;
private final Method method;
private MethodSpy(final Object instance, final Method method) {
this.instance = instance;
this.method = method;
}
static <T> MethodSpy<T> spyMethod(final Class<?> declaringClass, final Object instance, final String methodName, final Class<?>... parameterTypes)
throws NoSuchMethodException {
final Method method = declaringClass.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return new MethodSpy<>(instance, method);
}
#Override
public T get() {
// my javac generates useless new Object[0] if no args passed
return apply(emptyObjectArray);
}
#Override
public T apply(final Object[] arguments) {
try {
#SuppressWarnings("unchecked")
final T value = (T) method.invoke(instance, arguments);
return value;
} catch ( final IllegalAccessException | InvocationTargetException ex ) {
throw new RuntimeException(ex);
}
}
}
HugeJsonReaderDemo.java
And here is a demo that uses that method to read a huge JSON and redirect its string values to a another file.
public static void main(final String... args)
throws IOException {
try ( final EnhancedGson25JsonReader input = getEnhancedGson25JsonReader(new InputStreamReader(new FileInputStream("./huge.json")));
final Writer output = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("./huge.json.STRINGS"))) ) {
while ( input.hasNext() ) {
final JsonToken token = input.peek();
switch ( token ) {
case BEGIN_OBJECT:
input.beginObject();
break;
case NAME:
input.nextName();
break;
case STRING:
input.nextSlicedString(output::write);
break;
default:
throw new AssertionError(token);
}
}
}
}
I successfully extracted the fields above to a file. The input file was 544 MB (570 425 371 bytes) length and generated out of the following JSON chunks:
{"result":"OK","base64":"
JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC × 16777216 (2^24)
"}
And the result is (since I just redirect all strings to the file):
OK
JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC × 16777216 (2^24)
I think that you faced with a very interesting issue. It would be nice to have some feedback from the GSON team on possible API enhancement.

How can I use BeanUtils converter to List?

Here, the request Param string is :
firstName=jack&lastName=lily&gender=1&foods=Steak&foods=Pizza&quote=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day
And Mapped class is :
public class Student {
private String firstName;
private String lastName;
private Integer gender;
private List<String> foods;
private String quote;
private String education;
private String tOfD;
getXxx()....;
setXxx()....;
}
And Now, I want to write a generic util class to convert the string to a bean.
public final class InjectUtil<T> {
private static final Logger LOGGER = LoggerFactory.getLogger(InjectUtil.class);
public static <T> T converter2Obj(String source, Class<T> tClass) {
T t = null;
try {
t = tClass.newInstance();
if(source != null && source.length() > 0) {
String[] fields = source.split("&");
for(String field : fields) {
String[] fieldKeyValue = field.split("\\=");
String fieldKey = fieldKeyValue[0];
String fieldValue = fieldKeyValue[1];
// help
}
}
} catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return t;
}
}
take care of the help, how can i use BeanUtils converter the "foods=Steak&foods=Pizza" to the List attribute.
Here is a way of doing it :
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
public final class InjectUtil<T> {
// private static final Logger LOGGER =
// LoggerFactory.getLogger(InjectUtil.class);
public static <T> T converter2Obj(String source, Class<T> tClass) {
T t = null;
try {
t = tClass.newInstance();
Map<String, Object> params = new HashMap<String, Object>();
if (source != null && source.length() > 0) {
String[] fields = source.split("&");
for (String field : fields) {
String[] fieldKeyValue = field.split("\\=");
String fieldKey = fieldKeyValue[0];
String fieldValue = fieldKeyValue[1];
if (params.containsKey(fieldKey)) {
//the key does not exist as yet
Object keyValueRetrieved = params.get(fieldKey);
if (keyValueRetrieved instanceof String) {
//key exists , it is single value that has been added now.
//change that now to a list to add more values
ArrayList<String> values = new ArrayList<String>();
values.add(keyValueRetrieved.toString());
values.add(fieldValue);
params.put(fieldKey, values);
} else {
//key exists , it is a list already. Add more values
((ArrayList<String>) keyValueRetrieved).add(fieldValue);
}
} else {
params.put(fieldKey, fieldValue);
}
}
}
BeanUtils.populate(t, params);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("--------------------------------------------");
System.out.println(t.toString());
System.out.println("--------------------------------------------");
return t;
}
}
There are optimizations you can do , hopefully this gives you an idea
You can use as follows, you need to populate foodList (with values as [Steak,Pizza]) and then set to the bean using following method.
PropertyUtils.setProperty(studentBean, "foods", foodList);
or
BeanUtils.setProperty(studentBean, "foods", foodList);

Create a lucene romanian stemmer in java netbeans

I need to do a simple search engine which can recognize and stem Romanian words, including those with diacritics. I used RomanianAnalyzer, but it does not do the right stemming when it comes to the same word written with and without diacritics.
Can you help me with a code for adding/modifying an existing Romanian stemmer?
PS: I edited the question, to be more clear.
You can copy the RomanianAnalyzer source to create a custom analyzer, and add a filter to the analysis chain in the createComponents method. ASCIIFoldingFilter would probably be what you are looking for. I would add it to the end, to be sure that you don't mess up the stemmer when removing the diacritics.
public final class RomanianASCIIAnalyzer extends StopwordAnalyzerBase {
private final CharArraySet stemExclusionSet;
public final static String DEFAULT_STOPWORD_FILE = "stopwords.txt";
private static final String STOPWORDS_COMMENT = "#";
public static CharArraySet getDefaultStopSet(){
return DefaultSetHolder.DEFAULT_STOP_SET;
}
private static class DefaultSetHolder {
static final CharArraySet DEFAULT_STOP_SET;
static {
try {
DEFAULT_STOP_SET = loadStopwordSet(false, RomanianAnalyzer.class,
DEFAULT_STOPWORD_FILE, STOPWORDS_COMMENT);
} catch (IOException ex) {
throw new RuntimeException("Unable to load default stopword set");
}
}
}
public RomanianASCIIAnalyzer() {
this(DefaultSetHolder.DEFAULT_STOP_SET);
}
public RomanianASCIIAnalyzer(CharArraySet stopwords) {
this(stopwords, CharArraySet.EMPTY_SET);
}
public RomanianASCIIAnalyzer(CharArraySet stopwords, CharArraySet stemExclusionSet) {
super(stopwords);
this.stemExclusionSet = CharArraySet.unmodifiableSet(CharArraySet.copy(stemExclusionSet));
}
#Override
protected TokenStreamComponents createComponents(String fieldName) {
final Tokenizer source = new StandardTokenizer();
TokenStream result = new StandardFilter(source);
result = new LowerCaseFilter(result);
result = new StopFilter(result, stopwords);
if(!stemExclusionSet.isEmpty())
result = new SetKeywordMarkerFilter(result, stemExclusionSet);
result = new SnowballFilter(result, new RomanianStemmer());
//This following line is the addition made to the RomanianAnalyzer source.
result = new ASCIIFoldingFilter(result);
return new TokenStreamComponents(source, result);
}
}

How do I "register" a new Module Type in an IntelliJ Plugin?

I am a beginner when it comes to IntelliJ plugin development but i want my plugin to register a new Module Type in the "New Project" / "New Module" windows.
I already searched through the Documentation for plugin developers but wasn't able to find anything useful. I also looked at existing plugins like Kotlin and Scala which also add new Module types but I can't figure out how to get a finished ModuleType to show up in the dialogs mentioned above.
What do I have to change in the plugin.xml file? I already added extensions and created java classes for ModuleType, ModuleBuilder and the ModuleConfigurationExtensionProvider but that doesn't change anything.
I hope you can help me and thanks in advance.
This can be achieved through New Project Wizard feature of IntelliJ IDEA, by providing your Module / Project type implementation class of ModuleBuilder i.e by extending the intelliJ IDEA provided extension point for the same (com.intellij).
You need the below changes to make in your plugin.xml for making appear your new Module / Project type in New Project Wizard project /modules types list.
<extensions defaultExtensionNs="com.intellij">
<moduleBuilder builderClass="com.yourcompany.wizards.YourModuleBuilder"/>
</extensions>
Provide your ModuleBuilder class with package to buildlerClass attribute, thats enough.
Here is sample ModuleBuilder implementation:
public class AsposeJavaModuleBuilder extends ModuleBuilder implements SourcePathsBuilder {
private Project myProject;
ResourceBundle bundle = ResourceBundle.getBundle("Bundle");
#Override
public String getBuilderId() {
return getClass().getName();
}
#Override
public String getPresentableName() {
return "Aspose Application";
}
#Override
public String getDescription() {
return bundle.getString("AsposeWizardPanel.myMainPanel.description");
}
#Override
public Icon getBigIcon() {
return AsposeIcons.AsposeMedium;
}
#Override
public Icon getNodeIcon() {
return AsposeIcons.AsposeLogo;
}
#Override
public ModuleWizardStep[] createWizardSteps(#NotNull WizardContext wizardContext, #NotNull ModulesProvider modulesProvider) {
return new ModuleWizardStep[]{
new AsposeAPIsWizardStep(this, wizardContext),
};
}
#Override
public void setupRootModel(ModifiableRootModel rootModel) throws com.intellij.openapi.options.ConfigurationException {
setMyProject(rootModel.getProject());
final CompilerModuleExtension compilerModuleExtension = rootModel.getModuleExtension(CompilerModuleExtension.class);
compilerModuleExtension.setExcludeOutput(true);
if (myJdk != null) {
rootModel.setSdk(myJdk);
} else {
rootModel.inheritSdk();
}
ContentEntry contentEntry = doAddContentEntry(rootModel);
if (contentEntry != null) {
final List<Pair<String, String>> sourcePaths = getSourcePaths();
if (sourcePaths != null) {
for (final Pair<String, String> sourcePath : sourcePaths) {
String first = sourcePath.first;
new File(first).mkdirs();
final VirtualFile sourceRoot = LocalFileSystem.getInstance()
.refreshAndFindFileByPath(FileUtil.toSystemIndependentName(first));
if (sourceRoot != null) {
contentEntry.addSourceFolder(sourceRoot, false, sourcePath.second);
}
}
}
}
if (myCompilerOutputPath != null) {
// should set only absolute paths
String canonicalPath;
try {
canonicalPath = FileUtil.resolveShortWindowsName(myCompilerOutputPath);
} catch (IOException e) {
canonicalPath = myCompilerOutputPath;
}
compilerModuleExtension
.setCompilerOutputPath(VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(canonicalPath)));
} else {
compilerModuleExtension.inheritCompilerOutputPath(true);
}
LibraryTable libraryTable = rootModel.getModuleLibraryTable();
for (Pair<String, String> libInfo : myModuleLibraries) {
final String moduleLibraryPath = libInfo.first;
final String sourceLibraryPath = libInfo.second;
Library library = libraryTable.createLibrary();
Library.ModifiableModel modifiableModel = library.getModifiableModel();
modifiableModel.addRoot(getUrlByPath(moduleLibraryPath), OrderRootType.CLASSES);
if (sourceLibraryPath != null) {
modifiableModel.addRoot(getUrlByPath(sourceLibraryPath), OrderRootType.SOURCES);
}
modifiableModel.commit();
}
RunnableHelper.runWhenInitialized(getMyProject(), new Runnable() {
public void run() {
System.out.println("Hello I came here");
final LibraryTablesRegistrar libTablesRegistrar = LibraryTablesRegistrar.getInstance();
final LibraryTable libraryTable = libTablesRegistrar.getLibraryTable(getMyProject());
final LibraryTable.ModifiableModel libTableModel = libraryTable.getModifiableModel();
Library library = libTableModel.createLibrary(AsposeConstants.LIBRARY_NAME);
libTableModel.commit();
#NonNls final String path = getContentEntryPath() + File.separator + AsposeConstants.LIB_FOLDER;
new File(path).mkdirs();
for (AsposeJavaAPI api : AsposeProject.getApiList().values()) {
System.out.println("Hello I came here2");
if (api.is_selected()) {
try {
System.out.println("Hello I came here3");
AsposeAPIsManager.copyDirectory(AsposeAPIsManager.getLibaryDownloadPath() + api.get_name().toLowerCase(), path + File.separator + api.get_name());
} catch (IOException ex) {
ex.printStackTrace();
}
String[] children = new File(path + File.separator + api.get_name().toLowerCase() + File.separator).list();
for (String _child : children) {
String jarPath = "jar://" + path + File.separator + api.get_name() + File.separator + _child + "!/";
Library.ModifiableModel model = library.getModifiableModel();
model.addRoot(jarPath, OrderRootType.CLASSES);
model.commit();
}
}
}
Collection<Module> modules = ModuleUtil.getModulesOfType(getMyProject(), StdModuleTypes.JAVA);
Iterator itr = modules.iterator();
Module module = null;
while (itr.hasNext()) {
module = (Module) itr.next();
break;
}
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
final Library lib = libraryTable.getLibraryByName(AsposeConstants.LIBRARY_NAME);
if (moduleRootModel.findLibraryOrderEntry(lib) == null) {
moduleRootModel.addLibraryEntry(lib);
}
moduleRootModel.commit();
}
});
}
#Override
public String getGroupName() {
return JavaModuleType.JAVA_GROUP;
}
public Project getMyProject() {
return myProject;
}
public void setMyProject(Project myProject) {
this.myProject = myProject;
}
#Nullable
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
AsposeIntroWizardStep step = new AsposeIntroWizardStep();
Disposer.register(parentDisposable, step);
return step;
}
private String myCompilerOutputPath;
// Pair<Source Path, Package Prefix>
private List<Pair<String, String>> mySourcePaths;
// Pair<Library path, Source path>
private final List<Pair<String, String>> myModuleLibraries = new ArrayList<Pair<String, String>>();
public final void setCompilerOutputPath(String compilerOutputPath) {
myCompilerOutputPath = acceptParameter(compilerOutputPath);
}
public List<Pair<String, String>> getSourcePaths() {
if (mySourcePaths == null) {
final List<Pair<String, String>> paths = new ArrayList<Pair<String, String>>();
#NonNls final String path = getContentEntryPath() + File.separator + "src";
new File(path).mkdirs();
paths.add(Pair.create(path, ""));
return paths;
}
return mySourcePaths;
}
public void setSourcePaths(List<Pair<String, String>> sourcePaths) {
mySourcePaths = sourcePaths != null ? new ArrayList<Pair<String, String>>(sourcePaths) : null;
}
public void addSourcePath(Pair<String, String> sourcePathInfo) {
if (mySourcePaths == null) {
mySourcePaths = new ArrayList<Pair<String, String>>();
}
mySourcePaths.add(sourcePathInfo);
}
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
#Override
public boolean isSuitableSdkType(SdkTypeId sdkType) {
return sdkType instanceof JavaSdkType;
}
#Nullable
#Override
public ModuleWizardStep modifySettingsStep(#NotNull SettingsStep settingsStep) {
return StdModuleTypes.JAVA.modifySettingsStep(settingsStep, this);
}
private static String getUrlByPath(final String path) {
return VfsUtil.getUrlForLibraryRoot(new File(path));
}
public void addModuleLibrary(String moduleLibraryPath, String sourcePath) {
myModuleLibraries.add(Pair.create(moduleLibraryPath, sourcePath));
}
#Nullable
protected static String getPathForOutputPathStep() {
return null;
}
}
For complete source code reference for creating new Module / Project Types in IntelliJ IDEA, please see the source code of Aspose Project Wizard (an IntelliJ IDEA Plugin By Aspose pty Ltd)
Source codes can be downloaded from the following URL:
https://asposejetbrains.codeplex.com/

Categories