org.nuiton.eugene.java.extension.ImportsManager Maven / Gradle / Ivy
/*
* #%L
* EUGene :: EUGene
*
* $Id: ImportsManager.java 1174 2012-08-17 08:44:36Z tchemit $
* $HeadURL: https://nuiton.org/svn/eugene/tags/eugene-2.7.4/eugene/src/main/java/org/nuiton/eugene/java/extension/ImportsManager.java $
* %%
* Copyright (C) 2004 - 2010 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.eugene.java.extension;
import org.apache.commons.lang3.StringUtils;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.JavaGeneratorUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Class used in generators that allows to manage easily imports. A first-pass
* allow to register imports, and in a second-pass, returns the type to use in
* generated code.
*
* @author athimel
* @author tchemit
* @version $Id: ImportsManager.java 1174 2012-08-17 08:44:36Z tchemit $
* @since 2.0.0
*/
public class ImportsManager {
/**
* Internal states of the imports manager.
*
* @see #state
*/
private enum State {
FILLING, READING
}
private static Set primitiveTypes;
static {
primitiveTypes = new HashSet();
primitiveTypes.add("byte");
primitiveTypes.add("Byte");
primitiveTypes.add("short");
primitiveTypes.add("Short");
primitiveTypes.add("int");
primitiveTypes.add("Integer");
primitiveTypes.add("long");
primitiveTypes.add("Long");
primitiveTypes.add("float");
primitiveTypes.add("Float");
primitiveTypes.add("double");
primitiveTypes.add("Double");
primitiveTypes.add("char");
primitiveTypes.add("Char");
primitiveTypes.add("String");
primitiveTypes.add("boolean");
primitiveTypes.add("Boolean");
primitiveTypes.add("void");
}
private Map imports = new HashMap();
private State state = State.FILLING;
/**
* From the given class, add it to the imports list.
*
* @param clazz the class to import
* @return true if import add was successful
* @see ImportsManager#addImport(String)
*/
public boolean addImport(Class> clazz) {
return addImport(clazz.getName());
}
/**
* From the given fqn (fully qualified name), add it to the imports list.
* If there is a conflict adding this import, will return false.
* If reading of the imports has started, this method will return false,
* unless type does not need to be imported.
*
* @param fqn the fully qualified name to import
* @return true if import add was successful
*/
public boolean addImport(String fqn) {
// don't include null fqn
if (fqn == null) {
return false;
}
int lastDotIndex = getLastDotIndex(fqn);
// if no package don't include it
if (lastDotIndex == -1) {
return true;
}
// Exclude java.lang classes
if (fqn.trim().isEmpty() ||
fqn.startsWith("java.lang.") && lastDotIndex == 9) {
// reacts as if it was imported
return true;
}
// Exclude primitive types
if (primitiveTypes.contains(fqn)) {
// was not imported
return false;
}
if (fqn.endsWith("[]")) {
// fqn contains an array definition
String simpleFQN = fqn.substring(0, fqn.length() - 2);
return addImport(simpleFQN);
}
if (JavaGeneratorUtil.containsGenerics(fqn)) {
// Generics case :
String[] parts = JavaGeneratorUtil.splitGeneric(fqn);
boolean doImport = false;
if (addImport(parts[0])) {
doImport = true;
}
for (int i = 1, partsLength = parts.length; i < partsLength; i++) {
String part = parts[i];
addImport(part);
}
return doImport;
}
// // Reject generics
// if (fqn.contains("<") || fqn.contains(">")) {
// return false;
// }
String name = fqn.substring(lastDotIndex + 1);
String inPlaceFqn = imports.get(name);
if (inPlaceFqn == null) {
// Someone has started to read imports, impossible to add some more
if (state == State.READING) {
return false;
} else {
imports.put(name, fqn);
return true;
}
}
// if fqn is not the same, return false. Otherwise, no need to override.
return inPlaceFqn.equals(fqn);
}
/**
* Accorging to the already added types, returns the type to write in file.
* If there is a conflict, returns the fully qualified name, otherwise
* returns the simple name
*
* @param clazz the clazz to add
* @return the fqn or simple name according to in-place imports
* @since 2.3.2
*/
public String getType(Class> clazz) {
String type = getType(clazz.getName());
return type;
}
/**
* Accorging to the already added types, returns the type to write in file.
* If there is a conflict, returns the fully qualified name, otherwise
* returns the simple name
*
* @param fqn the fully qualified name to add
* @return the fqn or simple name according to in-place imports
*/
public String getType(String fqn) {
boolean importResult = addImport(fqn);
if (JavaGeneratorUtil.containsGenerics(fqn)) {
String[] parts = JavaGeneratorUtil.splitGeneric(fqn);
for (int i = 0; i < parts.length; i++) {
String part = parts[i];
parts[i] = getType(part);
}
return JavaGeneratorUtil.joinGeneric(parts);
}
if (!importResult) {
// There is a conflict, do not use simple name
return fqn;
}
// No conflict, use simple name
int packageEndIndex = getLastDotIndex(fqn);
if (packageEndIndex == -1) {
return fqn;
} else {
return fqn.substring(packageEndIndex + 1);
}
}
public String getReturnType(String returnType) {
if (StringUtils.isBlank(returnType)) {
return null;
}
if (JavaGeneratorUtil.containsGenerics(returnType)) {
// the return type is in two parts : <...> ...
String[] parts =
GeneratorUtil.splitGenericDefinition(returnType);
if (parts.length == 1) {
// no generic definition
return getType(returnType);
}
String genericDef = parts[0];
String strictReturnType = parts[1];
if (StringUtils.isNotBlank(genericDef)) {
genericDef += " ";
}
return genericDef + getType(strictReturnType);
} else {
return getType(returnType);
}
}
/**
* List the imports. This method will remove the useless imports according
* to the given packageName (no need to import a class in the same package)
*
* @param packageName the current package name (to avoid useless imports)
* @return the imports alphabeticaly sorted
*/
public List getImports(String packageName) {
state = State.READING;
List result = new ArrayList();
int packageLength = packageName.length();
String packagePrefix = packageName + ".";
for (String fqn : imports.values()) {
int lastDotIndex = getLastDotIndex(fqn);
// only keep sub package of given package
if (!(lastDotIndex == packageLength &&
fqn.startsWith(packagePrefix))) {
result.add(fqn);
}
}
Collections.sort(result);
return result;
}
/**
* Method to reset imports list. If imports has been listed, it becomes back
* possible to add imports.
*/
public void clearImports() {
imports.clear();
state = State.FILLING;
}
/**
* Obtains the last dot index in the given fqn.
*
* @param fqn the fqn to test
* @return the last index of a dot in given fqn
* @since 2.3.2
*/
public int getLastDotIndex(String fqn) {
return fqn.lastIndexOf(".");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy