From 87a8f2bc0229d1eab82ab25acc2d7533c93096fe Mon Sep 17 00:00:00 2001 From: suva Date: Thu, 26 Dec 2013 15:17:00 +0200 Subject: [PATCH] Added Support of JAXB2.1 --- pom.xml | 286 +- .../addon/xew/XmlElementWrapperPlugin.java | 2439 ++++++++--------- .../annotation_reference/ObjectFactory.java | 119 - .../xew/annotation_reference/SearchMulti.java | 75 - .../addon/xew/different_namespaces/Entry.java | 2 +- .../different_namespaces/ObjectFactory.java | 48 - .../ObjectFactory.java | 64 - .../ObjectFactory.java | 56 - .../element_with_parent/ObjectFactory.java | 56 - .../xew/inner_element/ObjectFactory.java | 56 - .../ObjectFactory.java | 86 - .../impl/ObjectFactory.java | 85 - 12 files changed, 1333 insertions(+), 2039 deletions(-) delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/SearchMulti.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_as_parametrisation/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_referenced_twice/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_with_parent/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/ObjectFactory.java delete mode 100644 src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/impl/ObjectFactory.java diff --git a/pom.xml b/pom.xml index 7872e98..0482c50 100644 --- a/pom.xml +++ b/pom.xml @@ -1,161 +1,161 @@ - 4.0.0 + 4.0.0 - com.github.jaxb-xew-plugin - jaxb-xew-plugin - jar - 1.2-SNAPSHOT + com.github.jaxb-xew-plugin + jaxb-xew-plugin21 + jar + 1.0 - - org.sonatype.oss - oss-parent - 7 - + + org.sonatype.oss + oss-parent + 7 + - JAXB @XmlElementWrapper Plugin - 2012 - This JAXB plugin utilizes the power of @XmlElementWrapper annotation. Originally xjc trends to create wrapper classes which are the containers for collections. This plugin goes through all properties to find ones which can be represented in the model in more optimal way. - https://github.com/dmak/jaxb-xew-plugin + JAXB @XmlElementWrapper Plugin + 2012 + This JAXB plugin utilizes the power of @XmlElementWrapper annotation. Originally xjc trends to create wrapper classes which are the containers for collections. This plugin goes through all properties to find ones which can be represented in the model in more optimal way. + https://github.com/dmak/jaxb-xew-plugin - - https://github.com/dmak/jaxb-xew-plugin - scm:git:https://github.com/dmak/jaxb-xew-plugin.git - scm:git:https://dmak@github.com/dmak/jaxb-xew-plugin.git - HEAD - + + https://github.com/dmak/jaxb-xew-plugin + scm:git:https://github.com/dmak/jaxb-xew-plugin.git + scm:git:https://dmak@github.com/dmak/jaxb-xew-plugin.git + HEAD + - - GitHub - https://github.com/dmak/jaxb-xew-plugin/issues - + + GitHub + https://github.com/dmak/jaxb-xew-plugin/issues + - - - LGPLv3 License - http://www.gnu.org/licenses/lgpl-3.0.html - repo - - + + + LGPLv3 License + http://www.gnu.org/licenses/lgpl-3.0.html + repo + + - - - stage-release + + + stage-release - - - - - org.codehaus.mojo - versions-maven-plugin - 2.0 - - false - - - - maven-release-plugin - 2.3.2 + + + + + org.codehaus.mojo + versions-maven-plugin + 2.0 + + false + + + + maven-release-plugin + 2.3.2 - - true - release-@{project.version} - clean verify - - - - - - - + + true + release-@{project.version} + clean verify + + + + + + + - - - Bjarne Hansen - bjarne@conspicio.dk - - developer - - - - Dmitry Katsubo - dmitry.katsubo@gmail.com - http://www.linkedin.com/in/dkatsubo - http://www.epo.org/ - - developer - - - + + + Bjarne Hansen + bjarne@conspicio.dk + + developer + + + + Dmitry Katsubo + dmitry.katsubo@gmail.com + http://www.linkedin.com/in/dkatsubo + http://www.epo.org/ + + developer + + + - - - com.sun.xml.ws - jaxws-tools - 2.2.5 - - - commons-logging - commons-logging - 1.1.1 - + + + com.sun.xml.ws + jaxws-tools + 2.1.2 + + + commons-logging + commons-logging + 1.1.1 + - - junit - junit - 4.11 - test - - - org.apache.commons - commons-lang3 - 3.1 - test - - - commons-io - commons-io - 2.4 - test - - + + junit + junit + 4.11 + test + + + org.apache.commons + commons-lang3 + 3.1 + test + + + commons-io + commons-io + 2.4 + test + + - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + - - - org.codehaus.mojo - cobertura-maven-plugin - 2.5.2 - - - xml - html - - - - - cobertura-report - verify - - cobertura - - - - - - + + + org.codehaus.mojo + cobertura-maven-plugin + 2.5.2 + + + xml + html + + + + + cobertura-report + verify + + cobertura + + + + + + diff --git a/src/main/java/com/sun/tools/xjc/addon/xew/XmlElementWrapperPlugin.java b/src/main/java/com/sun/tools/xjc/addon/xew/XmlElementWrapperPlugin.java index 2983ba1..a73d06b 100644 --- a/src/main/java/com/sun/tools/xjc/addon/xew/XmlElementWrapperPlugin.java +++ b/src/main/java/com/sun/tools/xjc/addon/xew/XmlElementWrapperPlugin.java @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -51,13 +52,10 @@ import com.sun.codemodel.JAnnotationValue; import com.sun.codemodel.JClass; import com.sun.codemodel.JClassContainer; -import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JExpr; -import com.sun.codemodel.JExpression; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JFormatter; -import com.sun.codemodel.JGenerable; import com.sun.codemodel.JJavaName; import com.sun.codemodel.JMethod; import com.sun.codemodel.JMod; @@ -77,1263 +75,1204 @@ import org.apache.commons.logging.LogFactory; import org.xml.sax.ErrorHandler; +import com.sun.codemodel.JMods; + /** * The XML Element Wrapper plugin is a JAXB plugin for the XJC compiler enabling generation of "natural" Java classes * for handling collection types. The code generated will be annotated with {@link XmlElementWrapper} and * {@link XmlElement} annotations and will have no extra inner classes representing the immediate collection type. - * + * * @see plugin site * @see source code and binary packages - * + * * @author Bjarne Hansen * @author Dmitry Katsubo */ public class XmlElementWrapperPlugin extends Plugin { + private static final String PLUGIN_NAME = "Xxew"; + private static final String OPTION_NAME_DELETE = "-" + PLUGIN_NAME + ":delete"; + private static final String OPTION_NAME_INCLUDE = "-" + PLUGIN_NAME + ":includeFile"; + private static final String OPTION_NAME_EXCLUDE = "-" + PLUGIN_NAME + ":excludeFile"; + private static final String OPTION_NAME_SUMMARY = "-" + PLUGIN_NAME + ":summaryFile"; + private static final String OPTION_NAME_COLLECTION = "-" + PLUGIN_NAME + ":collection"; + private static final String OPTION_NAME_INSTANTIATE = "-" + PLUGIN_NAME + ":instantiate"; + private File includeFile = null; + /** + * List of classes for inclusion + */ + private Set include = null; + private File excludeFile = null; + /** + * List of classes for exclusion + */ + private Set exclude = null; + private File summaryFile = null; + private PrintWriter summary = null; + private Class collectionInterfaceClass = java.util.List.class; + private Class collectionImplClass = java.util.ArrayList.class; + private Instantiation instantiation = Instantiation.EARLY; + private boolean deleteCandidates = false; + // This is currently an experimental and not properly working feature, so keep this field set to false. + // Waiting for this bug to be resolved: http://java.net/jira/browse/JAXB-883 + //private boolean applyPluralForm = Ring.get(BIGlobalBinding.class).isSimpleMode(); + private static boolean applyPluralForm = false; + private static final String FACTORY_CLASS_NAME = "ObjectFactory"; + private Log logger; + static final String COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY = "org.apache.commons.logging.simplelog.defaultlog"; + + @Override + public String getOptionName() { + return PLUGIN_NAME; + } + + @Override + public String getUsage() { + return " -" + + PLUGIN_NAME + + ": Replace collection types with fields having the @XmlElementWrapper and @XmlElement annotations."; + } + + void initLoggerIfNecessary(Options opts) { + if (logger != null) + return; + + // Allow the caller to control the log level by explicitly setting this system variable: + if (System.getProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY) == null) { + String logLevel = "WARN"; + + if (opts.quiet) + logLevel = "FATAL"; + else if (opts.debugMode) + logLevel = "DEBUG"; + else if (opts.verbose) + logLevel = "INFO"; + + System.setProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY, logLevel); + } + + logger = LogFactory.getLog(getClass()); + } + + @Override + public void onActivated(Options opts) { + initLoggerIfNecessary(opts); + + logger.debug("JAXB Compilation started (XmlElementWrapperPlugin.onActivated):"); + logger.debug(" buildId : " + Options.getBuildID()); + logger.debug(" targetDir : " + opts.targetDir); + logger.debug(" defaultPackage : " + opts.defaultPackage); + logger.debug(" defaultPackage2 : " + opts.defaultPackage2); + logger.debug(" debug : " + opts.debugMode); + logger.debug(" verbose : " + opts.verbose); + logger.debug(" quiet : " + opts.quiet); + logger.debug(" grammars : " + opts.getGrammars().length); + + for (int i = 0; i < opts.getGrammars().length; i++) + logger.debug("\t [" + i + "]: " + opts.getGrammars()[i].getSystemId()); + } + + @Override + public int parseArgument(Options opts, String[] args, int i) throws BadCommandLineException, IOException { + initLoggerIfNecessary(opts); + + int recognized = 0; + String filename; + + String arg = args[i]; + logger.debug("Argument[" + i + "] = " + arg); + + if (arg.startsWith(OPTION_NAME_DELETE)) { + recognized++; + deleteCandidates = true; + } else if (arg.startsWith(OPTION_NAME_INCLUDE)) { + recognized++; + include = new HashSet(); + + if (arg.length() > OPTION_NAME_INCLUDE.length()) + filename = arg.substring(OPTION_NAME_INCLUDE.length()).trim(); + else { + filename = args[i + 1]; + recognized++; + } + + includeFile = new File(filename); + readCandidates(includeFile, include); + } else if (arg.startsWith(OPTION_NAME_EXCLUDE)) { + recognized++; + exclude = new HashSet(); + + if (arg.length() > OPTION_NAME_EXCLUDE.length()) + filename = arg.substring(OPTION_NAME_EXCLUDE.length()).trim(); + else { + filename = args[i + 1]; + recognized++; + } + + excludeFile = new File(filename); + readCandidates(excludeFile, exclude); + } else if (arg.startsWith(OPTION_NAME_SUMMARY)) { + recognized++; + if (arg.length() > OPTION_NAME_SUMMARY.length()) + filename = arg.substring(OPTION_NAME_SUMMARY.length()).trim(); + else { + filename = args[i + 1]; + recognized++; + } + + summaryFile = new File(filename); + summary = new PrintWriter(new FileOutputStream(summaryFile)); + } else if (arg.startsWith(OPTION_NAME_COLLECTION)) { + String ccn; + + recognized++; + if (arg.length() > OPTION_NAME_COLLECTION.length()) + ccn = arg.substring(OPTION_NAME_COLLECTION.length()).trim(); + else { + ccn = args[i + 1]; + recognized++; + } + try { + collectionImplClass = Class.forName(ccn); + } catch (ClassNotFoundException e) { + throw new BadCommandLineException(OPTION_NAME_COLLECTION + " " + ccn + ": Class not found."); + } + } else if (arg.startsWith(OPTION_NAME_INSTANTIATE)) { + String instantiate; + recognized++; + + if (arg.length() > OPTION_NAME_INSTANTIATE.length()) + instantiate = arg.substring(OPTION_NAME_INSTANTIATE.length()).trim().toUpperCase(); + else { + instantiate = args[i + 1].trim().toUpperCase(); + recognized++; + } + instantiation = Instantiation.valueOf(instantiate); + } else if (arg.startsWith("-" + PLUGIN_NAME + ":")) + throw new BadCommandLineException("Invalid argument " + arg); + + return recognized; + } + + @Override + public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) { + logger.debug("JAXB Process Model (run)..."); + + // Write summary information on the option for this compilation. + writeSummary("Compilation:"); + writeSummary(" JAXB version : " + Options.getBuildID()); + writeSummary(" Include file : " + (includeFile == null ? "" : includeFile)); + writeSummary(" Exclude file : " + (excludeFile == null ? "" : excludeFile)); + writeSummary(" Summary file : " + (summaryFile == null ? "" : summaryFile)); + writeSummary(" Instantiation mode : " + instantiation); + writeSummary(" Collection impl : " + collectionImplClass); + writeSummary(" Collection interface : " + collectionInterfaceClass); + writeSummary(" Delete candidates : " + deleteCandidates); + writeSummary(""); + + // Visit all classes generated by JAXB and find candidate classes for transformation. + Map candidatesMap = new HashMap(); + + // Write information on candidate classes to summary file. + writeSummary("Candidates:"); + + for (Iterator iter = findCandidateClasses(outline).iterator(); iter.hasNext();) { + Candidate candidate = iter.next(); + + if (isIncluded(candidate)) { + candidatesMap.put(candidate.getClassName(), candidate); + + writeSummary("\t[" + (candidate.isMarkedForRemoval() ? "!" : "+") + "]: " + getIncludeOrExcludeReason() + + ":\t" + candidate.getClassName()); + } else { + writeSummary("\t[-]: " + getIncludeOrExcludeReason() + ":\t" + candidate.getClassName()); + iter.remove(); + } + } + + writeSummary("\t" + candidatesMap.size() + " candidate(s) being considered."); + writeSummary(""); + + writeSummary("Modifications:"); + + int modificationCount = 0; + + // Visit all classes again to check if the candidate is not eligible for removal: + // * If there are classes that extend the candidate + // * If there are class fields, that refer the candidate by e.g. @XmlElementRef annotation + for (ClassOutline outlineClass : outline.getClasses()) { + // Get the implementation class for the current class. + JDefinedClass implClass = outlineClass.implClass; + + // We cannot remove candidates that have parent classes, but we can still substitute them: + Candidate parentCandidate = candidatesMap.get(implClass._extends().fullName()); + + if (parentCandidate != null) { + logger.debug("Candidate " + parentCandidate.getClassName() + " is a parent of " + implClass.name() + + " and hence won't be removed."); + parentCandidate.unmarkForRemoval(); + } + + // Visit all fields in this class. + for (FieldOutline field : outlineClass.getDeclaredFields()) { + // Only non-primitive fields are interesting. + if (!(field.getRawType() instanceof JClass)) + continue; + + JClass fieldType = (JClass) field.getRawType(); + + String fieldName = field.getPropertyInfo().getName(false); + + Candidate candidate = null; + + for (Candidate c : candidatesMap.values()) + // Skip fields with basic types as for example any class can be casted to Object. + if (fieldType.isAssignableFrom(c.getCandidateClass()) && !isTopClass(fieldType)) { + // If the given field has type T, it cannot be also in the list of parametrisations (e.g. T). + candidate = c; + break; + } // If the candidate T is referred from list of parametrisations (e.g. List), it cannot be removed. + // However field substitutions will take place. + else if (isListedAsParametrisation(c.getCandidateClass(), fieldType)) { + logger.debug("Candidate " + c.getClassName() + " is listed as parametrisation of " + + implClass.fullName() + "#" + fieldName + " and hence won't be removed."); + c.unmarkForRemoval(); + } + + if (candidate == null) { + checkAnnotationReference(candidatesMap, implClass.fields().get(fieldName)); + + continue; + } + + // We have a candidate field to be replaced with a wrapped version. Report finding to summary file. + writeSummary("\tReplacing field " + implClass.fullName() + "#" + fieldName + " with type " + + fieldType.name()); + modificationCount++; + + // The container class has to be deleted. Check that inner class has to be moved to it's parent. + if (moveInnerClassToParentIfNecessary(outline, candidate)) + modificationCount++; + + List fieldTypeParametrisations = candidate.getFieldClass().getTypeParameters(); + + // Create the new interface and collection classes using the specified interface and + // collection classes (configuration) with an element type corresponding to + // the element type from the collection present in the candidate class (narrowing). + JClass collectionInterfaceClass = outline.getCodeModel().ref(this.collectionInterfaceClass) + .narrow(fieldTypeParametrisations); + JClass collectionImplClass = outline.getCodeModel().ref(this.collectionImplClass) + .narrow(fieldTypeParametrisations); + + // Remove original field which refers to the inner class. + JFieldVar originalImplField = implClass.fields().get(fieldName); + implClass.removeField(originalImplField); + + if (isPluralFormApplicable(field)) { + String oldFieldName = fieldName; + + // Taken from com.sun.tools.xjc.reader.xmlschema.ParticleBinder#makeJavaName(): + fieldName = JJavaName.getPluralForm(fieldName); + field.getPropertyInfo().setName(false, fieldName); + + // Correct the @XmlType class-level annotation: + for (JAnnotationUse annotation : XmlElementWrapperPlugin.>getPrivateField(implClass, "annotations")) { + String annotationClassName = XmlElementWrapperPlugin.getPrivateField(annotation, "clazz") .name(); + + if (!annotationClassName.equals("XmlType")) + continue; + + // FIXME: Pending for https://java.net/jira/browse/JAXB-884 +// for (JAnnotationValue ann : ((JAnnotationArrayMember) annotation.getAnnotationMembers().get( +// "propOrder")).annotations()) { + // FIXME: There is no way to set the correct property name back to annotation. + //if (oldFieldName.equals(getAnnotationStringValue(ann))) { + // break; + //} +// } + + break; + } + } + + // Add new wrapped version of the field using the original field name. + // GENERATED CODE: protected I fieldName; + JFieldVar implField = implClass.field(JMod.PROTECTED, collectionInterfaceClass, fieldName); + + // If instantiation is specified to be "early", add code for creating new instance of the collection class. + if (instantiation == Instantiation.EARLY) { + logger.debug("Applying EARLY instantiation..."); + // GENERATED CODE: ... fieldName = new C(); + implField.init(JExpr._new(collectionImplClass)); + } + + // Annotate the new field with the @XmlElementWrapper annotation using the original field name. + JAnnotationUse xmlElementWrapperAnnotation = implField.annotate(XmlElementWrapper.class); + + JAnnotationValue wrapperXmlName = getXmlElementMemberExpression(originalImplField, "name"); + if (wrapperXmlName != null) + addParam(xmlElementWrapperAnnotation, "name", wrapperXmlName); + else + xmlElementWrapperAnnotation.param("name", originalImplField.name()); + + JAnnotationValue warpperXmlRequired = getXmlElementMemberExpression(originalImplField, "required"); + if (warpperXmlRequired != null) + addParam(xmlElementWrapperAnnotation, "required", warpperXmlRequired); + + // Namespace of the wrapper element + JAnnotationValue wrapperXmlNamespace = getXmlElementMemberExpression(originalImplField, "namespace"); + if (wrapperXmlNamespace != null) + addParam(xmlElementWrapperAnnotation, "namespace", wrapperXmlNamespace); + + // Annotate the new field with the @XmlElement annotation using the field name from the wrapped type as name. + JAnnotationUse xmlElementAnnotation = implField.annotate(XmlElement.class); + + JAnnotationValue xmlName = getXmlElementMemberExpression(candidate.getField(), "name"); + if (xmlName != null) + addParam(xmlElementAnnotation, "name", xmlName); + else + xmlElementAnnotation.param("name", candidate.getFieldName()); + + // Namespace of the element itself + JAnnotationValue xmlNamespace = getXmlElementMemberExpression(candidate.getField(), "namespace"); + if (xmlNamespace != null) + addParam(xmlElementAnnotation, "namespace", xmlNamespace); + else if (wrapperXmlNamespace != null) + // FIXME: Only theoretical case, as it cannot happen that element does not have a namespace, but wrapper element has: + addParam(xmlElementAnnotation,"namespace", wrapperXmlNamespace); + + if (candidate.isValueObjectDisabled() && candidate.getFieldParametrisationImpl() != null) + xmlElementAnnotation.param("type", candidate.getFieldParametrisationImpl()); + + // Custom java adapter + JAnnotationValue xmlJavaTypeAdapter = getXmlJavaTypeAdapterMemberExpression(candidate.getField()); + + if (xmlJavaTypeAdapter != null) + addParam(implField.annotate(XmlJavaTypeAdapter.class), "value", xmlJavaTypeAdapter); + + String fieldPublicName = field.getPropertyInfo().getName(true); + + JDefinedClass implementationInterface = null; + + for (Iterator iter = implClass._implements(); iter.hasNext();) { + JClass interfaceClass = iter.next(); + + // If value class implements some JVM interface it is not considered as such interface cannot be modified: + if (interfaceClass instanceof JDefinedClass + && deleteSettersGetters((JDefinedClass) interfaceClass, fieldPublicName)) { + implementationInterface = (JDefinedClass) interfaceClass; + break; + } + } + + // Find original getter and setter methods to remove. + deleteSettersGetters(implClass, fieldPublicName); + + if (isPluralFormApplicable(field)) { + fieldPublicName = JJavaName.getPluralForm(fieldPublicName); + field.getPropertyInfo().setName(true, fieldPublicName); + } + + // Add a new getter method returning the (wrapped) field added. + // GENERATED CODE: public I getFieldName() { ... return fieldName; } + JMethod getterMethod = implClass.method(JMod.PUBLIC, collectionInterfaceClass, "get" + fieldPublicName); + + if (instantiation == Instantiation.LAZY) { + logger.debug("Applying LAZY instantiation..."); + // GENERATED CODE: if (fieldName == null) fieldName = new C(); + getterMethod.body()._if(JExpr.ref(fieldName).eq(JExpr._null()))._then() + .assign(JExpr.ref(fieldName), JExpr._new(collectionImplClass)); + } + + // GENERATED CODE: return "fieldName"; + getterMethod.body()._return(JExpr.ref(fieldName)); + + // Add a new setter method: + // GENERATED CODE: public void setFieldName(I fieldName) { this.fieldName = fieldName; } + JMethod setterMethod = implClass.method(JMod.PUBLIC, outline.getCodeModel().VOID, "set" + + fieldPublicName); + + setterMethod.body().assign(JExpr._this().ref(fieldName), + setterMethod.param(collectionInterfaceClass, fieldName)); + + // Modify interface as well: + if (implementationInterface != null) { + writeSummary("\tCorrecting interface " + implementationInterface.fullName()); + + implementationInterface.method(JMod.PUBLIC, collectionInterfaceClass, "get" + fieldPublicName); + setterMethod = implementationInterface. + method(JMod.PUBLIC, outline.getCodeModel().VOID, "set" + + fieldPublicName); + setterMethod.param(collectionInterfaceClass, fieldName); + } + } + } + + writeSummary("\t" + modificationCount + " modification(s) to original code."); + writeSummary(""); + + int deletionCount = 0; + + if (deleteCandidates) + deletionCount = deleteCandidates(outline, candidatesMap.values()); + + writeSummary("\t" + deletionCount + " deletion(s) from original code."); + writeSummary(""); + + logger.debug("Closing summary..."); + closeSummary(); + + logger.debug("Done"); + + return true; + } + + /** + * If candidate class contains the inner class, which will be referred from collection, then this inner class has to + * be moved to top class. For example from
+ * {@code TopClass -> ContainerClass (marked for removal) -> ElementClass}
we need to get
+ * {@code TopClass (will have a collection) -> ElementClass}.
Also this move should be reflected on factory + * method names. + * + * @param context TODO + */ + private boolean moveInnerClassToParentIfNecessary(Outline outline, Candidate candidate) { + // Skip basic parametrisations like "List": + if (candidate.getFieldParametrisationClass() == null) + return false; + + JDefinedClass fieldParametrisationImpl = candidate.getFieldParametrisationImpl(); + + if (candidate.getCandidateClass() != fieldParametrisationImpl.parentContainer()) + return false; + + JDefinedClass fieldParametrisationClass = candidate.getFieldParametrisationClass(); + + String oldFactoryMethodName = fieldParametrisationClass.outer().name() + fieldParametrisationClass.name(); + + renameFactoryMethod(fieldParametrisationImpl._package()._getClass(FACTORY_CLASS_NAME), oldFactoryMethodName, + fieldParametrisationClass.name()); + + moveClassLevelUp(outline, fieldParametrisationImpl); + + if (candidate.isValueObjectDisabled()) { + renameFactoryMethod(fieldParametrisationClass._package()._getClass(FACTORY_CLASS_NAME), + oldFactoryMethodName, fieldParametrisationClass.name()); + + moveClassLevelUp(outline, fieldParametrisationClass); + } + + return true; + } + + /** + * Locate the candidates classes for substitution/removal. + * + * @return a map className -> Candidate + */ + private Collection findCandidateClasses(Outline outline) { + Map interfaceImplementations = new HashMap(); + + // Visit all classes to create a map "interfaceName -> ClassOutline". + // This map is later used to resolve implementations from interfaces. + for (ClassOutline classOutline : outline.getClasses()) + for (Iterator iter = classOutline.implClass._implements(); iter.hasNext();) { + JClass interfaceClass = iter.next(); + + if (interfaceClass instanceof JDefinedClass) + // Don't care if interfaces collide: value classes have exactly one implementation. + interfaceImplementations.put(interfaceClass.fullName(), classOutline); // FIXME: Generated model has one value class for each interface: + //assert oldClass == null; + } + + Collection candidates = new ArrayList(); + + JClass collectionClass = outline.getCodeModel().ref(Collection.class); + + // Visit all classes created by JAXB processing to collect all potential wrapper classes to be removed: + for (ClassOutline classOutline : outline.getClasses()) { + JDefinedClass candidateClass = classOutline.implClass; + + // * The candidate class should not extend any other model class (as the total number of properties in this case will be more than 1) + if (!isHiddenClass(candidateClass._extends())) + continue; + + JFieldVar field = null; + + // * The candidate class should have exactly one property + for (JFieldVar f : candidateClass.fields().values()) { + if ((f.mods().getValue() & JMod.STATIC) == JMod.STATIC) + continue; + + // If there are at least two non-static fields, we discard this candidate: + if (field != null) { + field = null; + break; + } - private static final String PLUGIN_NAME = "Xxew"; - private static final String OPTION_NAME_DELETE = "-" + PLUGIN_NAME + ":delete"; - private static final String OPTION_NAME_INCLUDE = "-" + PLUGIN_NAME + ":includeFile"; - private static final String OPTION_NAME_EXCLUDE = "-" + PLUGIN_NAME + ":excludeFile"; - private static final String OPTION_NAME_SUMMARY = "-" + PLUGIN_NAME + ":summaryFile"; - private static final String OPTION_NAME_COLLECTION = "-" + PLUGIN_NAME + ":collection"; - private static final String OPTION_NAME_INSTANTIATE = "-" + PLUGIN_NAME + ":instantiate"; - - private File includeFile = null; - /** - * List of classes for inclusion - */ - private Set include = null; - - private File excludeFile = null; - /** - * List of classes for exclusion - */ - private Set exclude = null; - - private File summaryFile = null; - private PrintWriter summary = null; - private Class collectionInterfaceClass = java.util.List.class; - private Class collectionImplClass = java.util.ArrayList.class; - private Instantiation instantiation = Instantiation.EARLY; - private boolean deleteCandidates = false; - - // This is currently an experimental and not properly working feature, so keep this field set to false. - // Waiting for this bug to be resolved: http://java.net/jira/browse/JAXB-883 - //private boolean applyPluralForm = Ring.get(BIGlobalBinding.class).isSimpleMode(); - private static boolean applyPluralForm = false; - - private static final String FACTORY_CLASS_NAME = "ObjectFactory"; - - private Log logger; - - static final String COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY = "org.apache.commons.logging.simplelog.defaultlog"; - - @Override - public String getOptionName() { - return PLUGIN_NAME; - } - - @Override - public String getUsage() { - return " -" - + PLUGIN_NAME - + ": Replace collection types with fields having the @XmlElementWrapper and @XmlElement annotations."; - } - - void initLoggerIfNecessary(Options opts) { - if (logger != null) { - return; - } - - // Allow the caller to control the log level by explicitly setting this system variable: - if (System.getProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY) == null) { - String logLevel = "WARN"; - - if (opts.quiet) { - logLevel = "FATAL"; - } - else if (opts.debugMode) { - logLevel = "DEBUG"; - } - else if (opts.verbose) { - logLevel = "INFO"; - } - - System.setProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY, logLevel); - } - - logger = LogFactory.getLog(getClass()); - } - - @Override - public void onActivated(Options opts) { - initLoggerIfNecessary(opts); - - logger.debug("JAXB Compilation started (XmlElementWrapperPlugin.onActivated):"); - logger.debug(" buildId : " + Options.getBuildID()); - logger.debug(" targetDir : " + opts.targetDir); - logger.debug(" defaultPackage : " + opts.defaultPackage); - logger.debug(" defaultPackage2 : " + opts.defaultPackage2); - logger.debug(" debug : " + opts.debugMode); - logger.debug(" verbose : " + opts.verbose); - logger.debug(" quiet : " + opts.quiet); - logger.debug(" grammars : " + opts.getGrammars().length); - - for (int i = 0; i < opts.getGrammars().length; i++) { - logger.debug("\t [" + i + "]: " + opts.getGrammars()[i].getSystemId()); - } - } - - @Override - public int parseArgument(Options opts, String[] args, int i) throws BadCommandLineException, IOException { - initLoggerIfNecessary(opts); - - int recognized = 0; - String filename; - - String arg = args[i]; - logger.debug("Argument[" + i + "] = " + arg); - - if (arg.startsWith(OPTION_NAME_DELETE)) { - recognized++; - deleteCandidates = true; - } - else if (arg.startsWith(OPTION_NAME_INCLUDE)) { - recognized++; - include = new HashSet(); - - if (arg.length() > OPTION_NAME_INCLUDE.length()) { - filename = arg.substring(OPTION_NAME_INCLUDE.length()).trim(); - } - else { - filename = args[i + 1]; - recognized++; - } - - includeFile = new File(filename); - readCandidates(includeFile, include); - } - else if (arg.startsWith(OPTION_NAME_EXCLUDE)) { - recognized++; - exclude = new HashSet(); - - if (arg.length() > OPTION_NAME_EXCLUDE.length()) { - filename = arg.substring(OPTION_NAME_EXCLUDE.length()).trim(); - } - else { - filename = args[i + 1]; - recognized++; - } - - excludeFile = new File(filename); - readCandidates(excludeFile, exclude); - } - else if (arg.startsWith(OPTION_NAME_SUMMARY)) { - recognized++; - if (arg.length() > OPTION_NAME_SUMMARY.length()) { - filename = arg.substring(OPTION_NAME_SUMMARY.length()).trim(); - } - else { - filename = args[i + 1]; - recognized++; - } - - summaryFile = new File(filename); - summary = new PrintWriter(new FileOutputStream(summaryFile)); - } - else if (arg.startsWith(OPTION_NAME_COLLECTION)) { - String ccn; - - recognized++; - if (arg.length() > OPTION_NAME_COLLECTION.length()) { - ccn = arg.substring(OPTION_NAME_COLLECTION.length()).trim(); - } - else { - ccn = args[i + 1]; - recognized++; - } - try { - collectionImplClass = Class.forName(ccn); - } - catch (ClassNotFoundException e) { - throw new BadCommandLineException(OPTION_NAME_COLLECTION + " " + ccn + ": Class not found."); - } - } - else if (arg.startsWith(OPTION_NAME_INSTANTIATE)) { - String instantiate; - recognized++; - - if (arg.length() > OPTION_NAME_INSTANTIATE.length()) { - instantiate = arg.substring(OPTION_NAME_INSTANTIATE.length()).trim().toUpperCase(); - } - else { - instantiate = args[i + 1].trim().toUpperCase(); - recognized++; - } - instantiation = Instantiation.valueOf(instantiate); - } - else if (arg.startsWith("-" + PLUGIN_NAME + ":")) { - throw new BadCommandLineException("Invalid argument " + arg); - } - - return recognized; - } - - @Override - public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) { - logger.debug("JAXB Process Model (run)..."); - - // Write summary information on the option for this compilation. - writeSummary("Compilation:"); - writeSummary(" JAXB version : " + Options.getBuildID()); - writeSummary(" Include file : " + (includeFile == null ? "" : includeFile)); - writeSummary(" Exclude file : " + (excludeFile == null ? "" : excludeFile)); - writeSummary(" Summary file : " + (summaryFile == null ? "" : summaryFile)); - writeSummary(" Instantiation mode : " + instantiation); - writeSummary(" Collection impl : " + collectionImplClass); - writeSummary(" Collection interface : " + collectionInterfaceClass); - writeSummary(" Delete candidates : " + deleteCandidates); - writeSummary(""); - - // Visit all classes generated by JAXB and find candidate classes for transformation. - Map candidatesMap = new HashMap(); - - // Write information on candidate classes to summary file. - writeSummary("Candidates:"); - - for (Iterator iter = findCandidateClasses(outline).iterator(); iter.hasNext();) { - Candidate candidate = iter.next(); - - if (isIncluded(candidate)) { - candidatesMap.put(candidate.getClassName(), candidate); - - writeSummary("\t[" + (candidate.isMarkedForRemoval() ? "!" : "+") + "]: " + getIncludeOrExcludeReason() - + ":\t" + candidate.getClassName()); - } - else { - writeSummary("\t[-]: " + getIncludeOrExcludeReason() + ":\t" + candidate.getClassName()); - iter.remove(); - } - } - - writeSummary("\t" + candidatesMap.size() + " candidate(s) being considered."); - writeSummary(""); - - writeSummary("Modifications:"); - - int modificationCount = 0; - - // Visit all classes again to check if the candidate is not eligible for removal: - // * If there are classes that extend the candidate - // * If there are class fields, that refer the candidate by e.g. @XmlElementRef annotation - for (ClassOutline outlineClass : outline.getClasses()) { - // Get the implementation class for the current class. - JDefinedClass implClass = outlineClass.implClass; - - // We cannot remove candidates that have parent classes, but we can still substitute them: - Candidate parentCandidate = candidatesMap.get(implClass._extends().fullName()); - - if (parentCandidate != null) { - logger.debug("Candidate " + parentCandidate.getClassName() + " is a parent of " + implClass.name() - + " and hence won't be removed."); - parentCandidate.unmarkForRemoval(); - } - - // Visit all fields in this class. - for (FieldOutline field : outlineClass.getDeclaredFields()) { - // Only non-primitive fields are interesting. - if (!(field.getRawType() instanceof JClass)) { - continue; - } - - JClass fieldType = (JClass) field.getRawType(); - - String fieldName = field.getPropertyInfo().getName(false); - - Candidate candidate = null; - - for (Candidate c : candidatesMap.values()) { - // Skip fields with basic types as for example any class can be casted to Object. - if (fieldType.isAssignableFrom(c.getCandidateClass()) && !isTopClass(fieldType)) { - // If the given field has type T, it cannot be also in the list of parametrisations (e.g. T). - candidate = c; - break; - } - // If the candidate T is referred from list of parametrisations (e.g. List), it cannot be removed. - // However field substitutions will take place. - else if (isListedAsParametrisation(c.getCandidateClass(), fieldType)) { - logger.debug("Candidate " + c.getClassName() + " is listed as parametrisation of " - + implClass.fullName() + "#" + fieldName + " and hence won't be removed."); - c.unmarkForRemoval(); - } - } - - if (candidate == null) { - checkAnnotationReference(candidatesMap, implClass.fields().get(fieldName)); - - continue; - } - - // We have a candidate field to be replaced with a wrapped version. Report finding to summary file. - writeSummary("\tReplacing field " + implClass.fullName() + "#" + fieldName + " with type " - + fieldType.name()); - modificationCount++; - - // The container class has to be deleted. Check that inner class has to be moved to it's parent. - if (moveInnerClassToParentIfNecessary(outline, candidate)) { - modificationCount++; - } - - List fieldTypeParametrisations = candidate.getFieldClass().getTypeParameters(); - - // Create the new interface and collection classes using the specified interface and - // collection classes (configuration) with an element type corresponding to - // the element type from the collection present in the candidate class (narrowing). - JClass collectionInterfaceClass = outline.getCodeModel().ref(this.collectionInterfaceClass) - .narrow(fieldTypeParametrisations); - JClass collectionImplClass = outline.getCodeModel().ref(this.collectionImplClass) - .narrow(fieldTypeParametrisations); - - // Remove original field which refers to the inner class. - JFieldVar originalImplField = implClass.fields().get(fieldName); - implClass.removeField(originalImplField); - - if (isPluralFormApplicable(field)) { - String oldFieldName = fieldName; - - // Taken from com.sun.tools.xjc.reader.xmlschema.ParticleBinder#makeJavaName(): - fieldName = JJavaName.getPluralForm(fieldName); - field.getPropertyInfo().setName(false, fieldName); - - // Correct the @XmlType class-level annotation: - for (JAnnotationUse annotation : implClass.annotations()) { - String annotationClassName = annotation.getAnnotationClass().name(); - - if (!annotationClassName.equals("XmlType")) { - continue; - } - - // FIXME: Pending for https://java.net/jira/browse/JAXB-884 - for (JAnnotationValue ann : ((JAnnotationArrayMember) annotation.getAnnotationMembers().get( - "propOrder")).annotations()) { - // FIXME: There is no way to set the correct property name back to annotation. - //if (oldFieldName.equals(getAnnotationStringValue(ann))) { - // break; - //} - } - - break; - } - } - - // Add new wrapped version of the field using the original field name. - // GENERATED CODE: protected I fieldName; - JFieldVar implField = implClass.field(JMod.PROTECTED, collectionInterfaceClass, fieldName); - - // If instantiation is specified to be "early", add code for creating new instance of the collection class. - if (instantiation == Instantiation.EARLY) { - logger.debug("Applying EARLY instantiation..."); - // GENERATED CODE: ... fieldName = new C(); - implField.init(JExpr._new(collectionImplClass)); - } - - // Annotate the new field with the @XmlElementWrapper annotation using the original field name. - JAnnotationUse xmlElementWrapperAnnotation = implField.annotate(XmlElementWrapper.class); - - JExpression wrapperXmlName = getXmlElementMemberExpression(originalImplField, "name"); - if (wrapperXmlName != null) { - xmlElementWrapperAnnotation.param("name", wrapperXmlName); - } - else { - xmlElementWrapperAnnotation.param("name", originalImplField.name()); - } - - JExpression warpperXmlRequired = getXmlElementMemberExpression(originalImplField, "required"); - if (warpperXmlRequired != null) { - xmlElementWrapperAnnotation.param("required", warpperXmlRequired); - } - - // Namespace of the wrapper element - JExpression wrapperXmlNamespace = getXmlElementMemberExpression(originalImplField, "namespace"); - if (wrapperXmlNamespace != null) { - xmlElementWrapperAnnotation.param("namespace", wrapperXmlNamespace); - } - - // Annotate the new field with the @XmlElement annotation using the field name from the wrapped type as name. - JAnnotationUse xmlElementAnnotation = implField.annotate(XmlElement.class); - - JExpression xmlName = getXmlElementMemberExpression(candidate.getField(), "name"); - if (xmlName != null) { - xmlElementAnnotation.param("name", xmlName); - } - else { - xmlElementAnnotation.param("name", candidate.getFieldName()); - } - - // Namespace of the element itself - JExpression xmlNamespace = getXmlElementMemberExpression(candidate.getField(), "namespace"); - if (xmlNamespace != null) { - xmlElementAnnotation.param("namespace", xmlNamespace); - } - else if (wrapperXmlNamespace != null) { - // FIXME: Only theoretical case, as it cannot happen that element does not have a namespace, but wrapper element has: - xmlElementAnnotation.param("namespace", wrapperXmlNamespace); - } - - if (candidate.isValueObjectDisabled() && candidate.getFieldParametrisationImpl() != null) { - xmlElementAnnotation.param("type", candidate.getFieldParametrisationImpl()); - } - - // Custom java adapter - JExpression xmlJavaTypeAdapter = getXmlJavaTypeAdapterMemberExpression(candidate.getField()); - - if (xmlJavaTypeAdapter != null) { - implField.annotate(XmlJavaTypeAdapter.class).param("value", xmlJavaTypeAdapter); - } - - String fieldPublicName = field.getPropertyInfo().getName(true); - - JDefinedClass implementationInterface = null; - - for (Iterator iter = implClass._implements(); iter.hasNext();) { - JClass interfaceClass = iter.next(); - - // If value class implements some JVM interface it is not considered as such interface cannot be modified: - if (interfaceClass instanceof JDefinedClass - && deleteSettersGetters((JDefinedClass) interfaceClass, fieldPublicName)) { - implementationInterface = (JDefinedClass) interfaceClass; - break; - } - } - - // Find original getter and setter methods to remove. - deleteSettersGetters(implClass, fieldPublicName); - - if (isPluralFormApplicable(field)) { - fieldPublicName = JJavaName.getPluralForm(fieldPublicName); - field.getPropertyInfo().setName(true, fieldPublicName); - } - - // Add a new getter method returning the (wrapped) field added. - // GENERATED CODE: public I getFieldName() { ... return fieldName; } - JMethod getterMethod = implClass.method(JMod.PUBLIC, collectionInterfaceClass, "get" + fieldPublicName); - - if (instantiation == Instantiation.LAZY) { - logger.debug("Applying LAZY instantiation..."); - // GENERATED CODE: if (fieldName == null) fieldName = new C(); - getterMethod.body()._if(JExpr.ref(fieldName).eq(JExpr._null()))._then() - .assign(JExpr.ref(fieldName), JExpr._new(collectionImplClass)); - } - - // GENERATED CODE: return "fieldName"; - getterMethod.body()._return(JExpr.ref(fieldName)); - - // Add a new setter method: - // GENERATED CODE: public void setFieldName(I fieldName) { this.fieldName = fieldName; } - JMethod setterMethod = implClass.method(JMod.PUBLIC, outline.getCodeModel().VOID, "set" - + fieldPublicName); - - setterMethod.body().assign(JExpr._this().ref(fieldName), - setterMethod.param(collectionInterfaceClass, fieldName)); - - // Modify interface as well: - if (implementationInterface != null) { - writeSummary("\tCorrecting interface " + implementationInterface.fullName()); - - implementationInterface.method(JMod.PUBLIC, collectionInterfaceClass, "get" + fieldPublicName); - setterMethod = implementationInterface.method(JMod.PUBLIC, outline.getCodeModel().VOID, "set" - + fieldPublicName); - setterMethod.param(collectionInterfaceClass, fieldName); - } - } - } - - writeSummary("\t" + modificationCount + " modification(s) to original code."); - writeSummary(""); - - int deletionCount = 0; - - if (deleteCandidates) { - deletionCount = deleteCandidates(outline, candidatesMap.values()); - } - - writeSummary("\t" + deletionCount + " deletion(s) from original code."); - writeSummary(""); - - logger.debug("Closing summary..."); - closeSummary(); - - logger.debug("Done"); - - return true; - } - - /** - * If candidate class contains the inner class, which will be referred from collection, then this inner class has to - * be moved to top class. For example from
- * {@code TopClass -> ContainerClass (marked for removal) -> ElementClass}
- * we need to get
- * {@code TopClass (will have a collection) -> ElementClass}.
- * Also this move should be reflected on factory method names. - * - * @param context - * TODO - */ - private boolean moveInnerClassToParentIfNecessary(Outline outline, Candidate candidate) { - // Skip basic parametrisations like "List": - if (candidate.getFieldParametrisationClass() == null) { - return false; - } - - JDefinedClass fieldParametrisationImpl = candidate.getFieldParametrisationImpl(); - - if (candidate.getCandidateClass() != fieldParametrisationImpl.parentContainer()) { - return false; - } + field = f; + } - JDefinedClass fieldParametrisationClass = candidate.getFieldParametrisationClass(); - - String oldFactoryMethodName = fieldParametrisationClass.outer().name() + fieldParametrisationClass.name(); - - renameFactoryMethod(fieldParametrisationImpl._package()._getClass(FACTORY_CLASS_NAME), oldFactoryMethodName, - fieldParametrisationClass.name()); - - moveClassLevelUp(outline, fieldParametrisationImpl); - - if (candidate.isValueObjectDisabled()) { - renameFactoryMethod(fieldParametrisationClass._package()._getClass(FACTORY_CLASS_NAME), - oldFactoryMethodName, fieldParametrisationClass.name()); - - moveClassLevelUp(outline, fieldParametrisationClass); - } - - return true; - } - - /** - * Locate the candidates classes for substitution/removal. - * - * @return a map className -> Candidate - */ - private Collection findCandidateClasses(Outline outline) { - Map interfaceImplementations = new HashMap(); - - // Visit all classes to create a map "interfaceName -> ClassOutline". - // This map is later used to resolve implementations from interfaces. - for (ClassOutline classOutline : outline.getClasses()) { - for (Iterator iter = classOutline.implClass._implements(); iter.hasNext();) { - JClass interfaceClass = iter.next(); - - if (interfaceClass instanceof JDefinedClass) { - // Don't care if interfaces collide: value classes have exactly one implementation. - interfaceImplementations.put(interfaceClass.fullName(), classOutline); - - // FIXME: Generated model has one value class for each interface: - //assert oldClass == null; - } - } - } - - Collection candidates = new ArrayList(); - - JClass collectionClass = outline.getCodeModel().ref(Collection.class); - - // Visit all classes created by JAXB processing to collect all potential wrapper classes to be removed: - for (ClassOutline classOutline : outline.getClasses()) { - JDefinedClass candidateClass = classOutline.implClass; - - // * The candidate class should not extend any other model class (as the total number of properties in this case will be more than 1) - if (!isHiddenClass(candidateClass._extends())) { - continue; - } - - JFieldVar field = null; - - // * The candidate class should have exactly one property - for (JFieldVar f : candidateClass.fields().values()) { - if ((f.mods().getValue() & JMod.STATIC) == JMod.STATIC) { - continue; - } - - // If there are at least two non-static fields, we discard this candidate: - if (field != null) { - field = null; - break; - } - - field = f; - } - - // "field" is null if there are no fields (or all fields are static) or there are more then two fields. - // The only property should be a collection, hence it should be class: - if (field == null || !(field.type() instanceof JClass)) { - continue; - } - - JClass fieldType = (JClass) field.type(); - - // * The property should be a collection - if (!collectionClass.isAssignableFrom(fieldType)) { - continue; - } - - List fieldParametrisations = fieldType.getTypeParameters(); - - // FIXME: All known collections have exactly one parametrisation type. - assert fieldParametrisations.size() == 1; - - // * The only one parametrisation type should not be java.lang.Object (the case for ) - // or java.io.Serializable / javax.xml.bind.JAXBElement (the case for ) - if (isTopClass(fieldParametrisations.get(0))) { - continue; - } - - JDefinedClass fieldParametrisationClass = null; - JDefinedClass fieldParametrisationImpl = null; - - // Parametrisations like "List" or "List" are not considered. - // They are substituted as is and do not require moving of classes. - if (fieldParametrisations.get(0) instanceof JDefinedClass) { - fieldParametrisationClass = (JDefinedClass) fieldParametrisations.get(0); - - ClassOutline fieldParametrisationClassOutline = interfaceImplementations.get(fieldParametrisationClass - .fullName()); - - if (fieldParametrisationClassOutline != null) { - assert fieldParametrisationClassOutline.ref == fieldParametrisationClass; - - fieldParametrisationImpl = fieldParametrisationClassOutline.implClass; - } - else { - fieldParametrisationImpl = fieldParametrisationClass; - } - } - - // We have a candidate class - Candidate candidate = new Candidate(candidateClass, field, fieldParametrisationClass, - fieldParametrisationImpl); - candidates.add(candidate); - - logger.debug("Candidate found: " + candidate.getClassName() + " [private " - + candidate.getFieldClass().name() + " " + candidate.getFieldName() + "]"); - } - - return candidates; - } - - /** - * Delete all candidate classes together with setter/getter methods and helper methods from - * ObjectFactory. - * - * @return the number of deletions performed - */ - private int deleteCandidates(Outline outline, Collection candidates) { - int deletionCount = 0; - - writeSummary("Deletions:"); - - // Visit all candidate classes. - for (Candidate candidate : candidates) { - // Only consider candidates that are actually included... - if (!isIncluded(candidate) || !candidate.isMarkedForRemoval()) { - continue; - } - - // Get the defined class for candidate class. - JDefinedClass candidateClass = candidate.getCandidateClass(); - - deleteFactoryMethod(candidate.getValueObjectFactoryClass(), candidateClass); - deletionCount++; - - deleteClass(outline, candidateClass); - deletionCount++; - - // Redo the same for interface: - if (candidate.isValueObjectDisabled()) { - deleteFactoryMethod(candidate.getObjectFactoryClass(), candidateClass); - deletionCount++; - - for (Iterator iter = candidateClass._implements(); iter.hasNext();) { - JClass interfaceClass = iter.next(); - - if (!isHiddenClass(interfaceClass)) { - deleteClass(outline, (JDefinedClass) interfaceClass); - deletionCount++; - } - } - } - } - - return deletionCount; - } - - // - // Model factory manipulation helpers. - // - - /** - * Rename methods in factory class: {@code createABC() -> createAC()}. - */ - private void renameFactoryMethod(JDefinedClass factoryClass, String oldMethodName, String newMethodName) { - for (JMethod method : factoryClass.methods()) { - String methodName = method.name(); - - if (!methodName.contains(oldMethodName)) { - continue; - } - - method.name(methodName.replace(oldMethodName, newMethodName)); - - writeSummary("Renamed " + methodName + " -> " + method.name() + " in " + factoryClass.fullName()); - } - } - - /** - * Remove method {@code ObjectFactory} that creates an object of a given {@code clazz}. - * - * @return {@code true} is such method was successfully located and removed - */ - private boolean deleteFactoryMethod(JDefinedClass factoryClass, JDefinedClass clazz) { - for (Iterator iter = factoryClass.methods().iterator(); iter.hasNext();) { - JMethod method = iter.next(); - - // Remove the methods: - // * public T createT() { return new T(); } - // * public JAXBElement createT(T value) { return new JAXBElement(QNAME, T.class, null, value); } - // FIXME: The last case is mostly theoretical and live example is not known. - if ((method.type() instanceof JDefinedClass && ((JDefinedClass) method.type()).isAssignableFrom(clazz)) - || isListedAsParametrisation(clazz, method.type())) { - writeSummary("\tRemoving method " + method.type().fullName() + " " + method.name() + "() from " - + factoryClass.fullName()); - iter.remove(); - - return true; - } - } - - return false; - } - - // - // Model manipulation helpers. - // - - /** - * Returns {@code true} if setter/getter with given public name was successfully removed from given class/interface. - */ - private boolean deleteSettersGetters(JDefinedClass clazz, String fieldPublicName) { - boolean result = false; - - for (Iterator iter = clazz.methods().iterator(); iter.hasNext();) { - JMethod m = iter.next(); - - if (m.name().equals("set" + fieldPublicName) || m.name().equals("get" + fieldPublicName)) { - iter.remove(); - result = true; - } - } - - return result; - } - - /** - * Move the given class to his grandparent (either class or package). - */ - private void moveClassLevelUp(Outline outline, JDefinedClass clazz) { - // Container can be a class or package: - JClassContainer container = clazz.parentContainer().parentContainer(); - setPrivateField(clazz, "outer", container); - - // FIXME: Pending https://java.net/jira/browse/JAXB-957 - if (container.isClass()) { - // Element class should be added as its container child: - JDefinedClass parentClass = (JDefinedClass) container; - - writeSummary("\tMoving inner class " + clazz.fullName() + " to class " + parentClass.fullName()); - - ((Map) getPrivateField(parentClass, "classes")).put(clazz.name(), clazz); - } - else { - JPackage parentPackage = (JPackage) container; - - writeSummary("\tMoving inner class " + clazz.fullName() + " to package " + parentPackage.name()); - - ((Map) getPrivateField(parentPackage, "classes")).put(clazz.name(), clazz); - - // In this scenario class should have "static" modifier reset: - setPrivateField(clazz.mods(), "mods", clazz.mods().getValue() & ~JMod.STATIC); - - for (ClassOutline classOutline : outline.getClasses()) { - if (classOutline.implClass == clazz) { - XSComponent sc = classOutline.target.getSchemaComponent(); - - // FIXME: Inner class is always a local declaration. - assert (sc instanceof XSDeclaration && ((XSDeclaration) sc).isLocal()); - - setPrivateField(sc, "anonymous", Boolean.FALSE); - } - } - } - } - - /** - * Remove the given class from it's parent class or package it is defined in. - */ - private void deleteClass(Outline outline, JDefinedClass clazz) { - if (clazz.parentContainer().isClass()) { - // The candidate class is an inner class. Remove the class from its parent class. - JDefinedClass parentClass = (JDefinedClass) clazz.parentContainer(); - - writeSummary("\tRemoving class " + clazz.fullName() + " from class " + parentClass.fullName()); - - for (Iterator iter = parentClass.classes(); iter.hasNext();) { - if (iter.next().equals(clazz)) { - iter.remove(); - break; - } - } - } - else { - // The candidate class is in a package. Remove the class from the package. - JPackage parentPackage = (JPackage) clazz.parentContainer(); - - writeSummary("\tRemoving class " + clazz.fullName() + " from package " + parentPackage.name()); - - parentPackage.remove(clazz); - - // And also remove the class from model. - for (Iterator iter = outline.getClasses().iterator(); iter.hasNext();) { - ClassOutline classOutline = iter.next(); - if (classOutline.implClass == clazz) { - outline.getModel().beans().remove(classOutline.target); - iter.remove(); - } - } - } - } - - /** - * Returns {@code true} if given class is a top of the class hierarchy like {@link Object} or {@link Serializable} - * or {@link JAXBElement}, or it is a customized super-class for all model beans. Basic JVM classes like - * {@link String} or {@link Integer} are not treated as top-classes: for them this method returns {@code false}. - */ - private static boolean isTopClass(JClass clazz) { - // We need a basis for narrowed class: - String className = clazz.erasure().fullName(); - - if ((className.equals(Object.class.getName()) || className.equals(Serializable.class.getName()) || className - .equals(JAXBElement.class.getName()))) { - return true; - } - - // See also https://java.net/jira/browse/JAXB-958 - return clazz instanceof JDefinedClass && ((JDefinedClass) clazz).isHidden(); - } - - /** - * Returns {@code true} if given class is hidden, that is not generated & saved by XJC. These are for example - * instances of {@link JCodeModel.JReferencedClass} (JVM-wide classes) or instances of {@link JDefinedClass} with - * hidden flag (customized super-class or super-interface). - */ - static boolean isHiddenClass(JClass clazz) { - // See also https://java.net/jira/browse/JAXB-958 - return !(clazz instanceof JDefinedClass) || ((JDefinedClass) clazz).isHidden(); - } - - /** - * Returns true of the given type is {@link JClass} and contains classToCheck - * in the list of parametrisations. - */ - private static boolean isListedAsParametrisation(JClass classToCheck, JType type) { - return type instanceof JClass && ((JClass) type).getTypeParameters().contains(classToCheck); - } - - /** - * Apply the plural form if there are no customizations. Assuming that customization is correct as may define the - * plural form in more correct way, e.g. "fieldsOfScience" instead of "fieldOfSciences". - */ - private static boolean isPluralFormApplicable(FieldOutline field) { - // FIXME: It looks like customizations are always empty: - return applyPluralForm && field.getPropertyInfo().getCustomizations().isEmpty(); - } - - /** - * Returns the string value of passed argument. - */ - private static final String toString(JGenerable generable) { - // There is hardly any clean universal way to get the value from e.g. JExpression except of serializing it. - // Compare JStringLiteral and JExp#dotclass(). - Writer w = new StringWriter(); - - generable.generate(new JFormatter(w)); - - // FIXME: Hopefully nobody will put quotes into annotation member value. - return w.toString().replace("\"", ""); - } - - // - // Annotation helpers. - // - - /** - * For the given annotatable check that all annotations (and all annotations within annotations recursively) do not - * refer any candidate for removal. - */ - private void checkAnnotationReference(Map candidatesMap, JAnnotatable annotatable) { - for (JAnnotationUse annotation : annotatable.annotations()) { - String annotationClassName = annotation.getAnnotationClass().name(); - - if (annotationClassName.equals("XmlElementRefs") || annotationClassName.equals("XmlElements")) { - checkAnnotationReference(candidatesMap, - (JAnnotationArrayMember) annotation.getAnnotationMembers().get("value")); - - continue; - } - - // FIXME: Dirty workaround for http://java.net/jira/browse/JAXB-784: - if (!(annotationClassName.equals("XmlElementRef") || annotationClassName.equals("XmlElement"))) { - continue; - } - - JExpression type = getAnnotationMemberExpression(annotation, "type"); - - if (type == null) { - // Can be the case for @XmlElement(name = "publication-reference", namespace = "http://mycompany.org/exchange") - // or any other annotation without "type" - continue; - } - - String typeClassName = toString(type).replace(".class", ""); - - Candidate candidate = candidatesMap.get(typeClassName); - - if (candidate != null) { - logger.debug("Candidate " + candidate.getClassName() - + " is used in XmlElements/XmlElementRef and hence won't be removed."); - candidate.unmarkForRemoval(); - } - } - } - - /** - * Returns the value of the given annotation member of {@link XmlElement} annotation for the given field. - */ - private static JExpression getXmlElementMemberExpression(JVar field, String annotationMember) { - return getAnnotationMemberExpression(field, "XmlElement", annotationMember); - } - - /** - * Returns the value of the "value" member of {@link XmlJavaTypeAdapter} annotation for the given field. - */ - private static JExpression getXmlJavaTypeAdapterMemberExpression(JVar field) { - return getAnnotationMemberExpression(field, "XmlJavaTypeAdapter", "value"); - } - - /** - * Returns the value of the given annotation member of given annotation for the given field. - */ - private static JExpression getAnnotationMemberExpression(JVar field, String annotationClassName, - String annotationMember) { - for (JAnnotationUse annotation : field.annotations()) { - if (annotation.getAnnotationClass().name().equals(annotationClassName)) { - return getAnnotationMemberExpression(annotation, annotationMember); - } - } - - return null; - } - - /** - * Returns the string value of annotation element. For example, for annotation - * @XmlElementRef(name = "last-name", namespace = "http://mycompany.org/exchange", type = JAXBElement.class) - * for member name the value last-name will be returned. - */ - private static final JExpression getAnnotationMemberExpression(JAnnotationUse annotation, String annotationMember) { - JAnnotationValue annotationValue = annotation.getAnnotationMembers().get(annotationMember); - - if (annotationValue == null) { - return null; - } - - // FIXME: Pending for https://java.net/jira/browse/JAXB-878 - return (JExpression) getPrivateField(annotationValue, "value"); - } - - // - // Reflection helpers. - // - - private static void setPrivateField(Object obj, String fieldName, Object newValue) { - setPrivateField(obj, obj.getClass(), fieldName, newValue); - } - - /** - * Set the {@code newValue} to private field {@code fieldName} of given object {@code obj}. - */ - private static void setPrivateField(Object obj, Class clazz, String fieldName, Object newValue) { - try { - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - field.set(obj, newValue); - } - catch (NoSuchFieldException e) { - if (clazz.getSuperclass() == Object.class) { - // Field is really not found: - throw new RuntimeException(e); - } - - // Try super class: - setPrivateField(obj, clazz.getSuperclass(), fieldName, newValue); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - /** - * Get the value of private field {@code fieldName} of given object {@code obj}. - */ - private static Object getPrivateField(Object obj, String fieldName) { - try { - Field field = obj.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - return field.get(obj); - } - catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - // - // Includes / excludes support. - // - - private boolean hasIncludes() { - return include != null; - } - - private boolean hasExcludes() { - return exclude != null; - } - - private boolean isIncluded(Candidate candidate) { - // - // A candidate is included if, ... - // 1. No includes and no excludes have been specified - // 2. Includes have been specified and candidate is included, and no excludes have been specified. - // 3. No includes have been specified and excludes have been specified and candidate is not in excludes. - // 4. Both includes and excludes have been specified and candidate is in includes and not in excludes. - // - if (!hasIncludes() && !hasExcludes()) { - return true; // [+] (default) - } - else if (hasIncludes() && !hasExcludes()) { - return include.contains(candidate.getClassName()); // [+/-] (included) - } - else if (!hasIncludes() && hasExcludes()) { - return !exclude.contains(candidate.getClassName()); // [+/-] (excluded) - } - else { - return include.contains(candidate.getClassName()) && !exclude.contains(candidate.getClassName()); // [+/-] (override) - } - } - - private String getIncludeOrExcludeReason() { - if (!hasIncludes() && !hasExcludes()) { - return "(default)"; // [+] (default) - } - else if (hasIncludes() && !hasExcludes()) { - return "(included)"; - } - else if (!hasIncludes() && hasExcludes()) { - return "(excluded)"; - } - else { - return "(override)"; - } - } - - /** - * Read all candidates from a given file into the given set. - */ - private static void readCandidates(File file, Set candidates) throws IOException { - BufferedReader input = new BufferedReader(new FileReader(file)); - String line; - - while ((line = input.readLine()) != null) { - line = line.trim(); - - // Lines starting with # are considered comments. - if (!line.startsWith("#")) { - candidates.add(line); - } - } - - input.close(); - } - - // - // Logging helpers - // - - private void writeSummary(String s) { - if (summary != null) { - summary.println(s); - } - - logger.info(s); - } - - private void closeSummary() { - if (summary != null) { - summary.close(); - } - } - - /** - * Types of collection instantiation modes. - */ - private enum Instantiation { - EARLY, LAZY - } - - /** - * Describes the collection container class -- a candidate for removal. - */ - private static class Candidate { - private JDefinedClass objectFactoryClass; - - private final JDefinedClass valueObjectFactoryClass; - - private final JDefinedClass candidateClass; - - private final JFieldVar field; - - private final JDefinedClass fieldParametrisationClass; - - private final JDefinedClass fieldParametrisationImpl; - - private boolean markedForRemoval = true; - - Candidate(JDefinedClass candidateClass, JFieldVar field, JDefinedClass fieldParametrizationClass, - JDefinedClass fieldParametrisationImpl) { - // If class has a non-hidden interface, then there is object factory in another package. - for (Iterator iter = candidateClass._implements(); iter.hasNext();) { - JClass interfaceClass = iter.next(); - - if (!isHiddenClass(interfaceClass)) { - objectFactoryClass = interfaceClass._package()._getClass(FACTORY_CLASS_NAME); - - if (objectFactoryClass != null) { - break; - } - } - } - - this.valueObjectFactoryClass = candidateClass._package()._getClass(FACTORY_CLASS_NAME); - this.candidateClass = candidateClass; - this.field = field; - this.fieldParametrisationClass = fieldParametrizationClass; - this.fieldParametrisationImpl = fieldParametrisationImpl; - - assert objectFactoryClass != valueObjectFactoryClass; - } - - /** - * Object Factory class for interface classes. It's usually located in {@code impl.} subpackage relative to - * {@code valueObjectFactoryClass} package. May be {@code null}. - */ - - public JDefinedClass getObjectFactoryClass() { - return objectFactoryClass; - } - - /** - * Object Factory class for value (implementation) classes. Is not {@code null}. - */ - public JDefinedClass getValueObjectFactoryClass() { - return valueObjectFactoryClass; - } - - /** - * Container class - */ - public JDefinedClass getCandidateClass() { - return candidateClass; - } - - /** - * Container class name - */ - public String getClassName() { - return candidateClass.fullName(); - } - - /** - * The only field in container class. - */ - public JFieldVar getField() { - return field; - } - - /** - * The name of the only field in container class. - */ - public String getFieldName() { - return field.name(); - } - - /** - * The class of the only field in container class. - */ - public JClass getFieldClass() { - return (JClass) field.type(); - } - - /** - * The only parametrisation class of the field. In case of basic parametrisation like {@link List} this - * property is {@code null}. - */ - public JDefinedClass getFieldParametrisationClass() { - return fieldParametrisationClass; - } - - /** - * If {@link #getFieldParametrisationClass()} is an interface, then this holds that same value. Otherwise it - * holds the implementation (value object) of {@link #getFieldParametrisationClass()}. In case of basic - * parametrisation like {@code List} this property is {@code null}. - */ - public JDefinedClass getFieldParametrisationImpl() { - return fieldParametrisationImpl; - } - - /** - * Returns {@code true} if the setting {@code } is active. - */ - public boolean isValueObjectDisabled() { - return objectFactoryClass != null; - } - - /** - * This flag controls if given candidate has green light to be removed. - */ - public boolean isMarkedForRemoval() { - return markedForRemoval; - } - - /** - * Signal that this candidate should not be removed from model on some reason. - */ - public void unmarkForRemoval() { - this.markedForRemoval = false; - } - - @Override - public String toString() { - return "Candidate[" + getClassName() + "]"; - } - } + // "field" is null if there are no fields (or all fields are static) or there are more then two fields. + // The only property should be a collection, hence it should be class: + if (field == null || !(field.type() instanceof JClass)) + continue; + + JClass fieldType = (JClass) field.type(); + + // * The property should be a collection + if (!collectionClass.isAssignableFrom(fieldType)) + continue; + + List fieldParametrisations = fieldType.getTypeParameters(); + + // FIXME: All known collections have exactly one parametrisation type. + assert fieldParametrisations.size() == 1; + + // * The only one parametrisation type should not be java.lang.Object (the case for ) + // or java.io.Serializable / javax.xml.bind.JAXBElement (the case for ) + if (isTopClass(fieldParametrisations.get(0))) + continue; + + JDefinedClass fieldParametrisationClass = null; + JDefinedClass fieldParametrisationImpl = null; + + // Parametrisations like "List" or "List" are not considered. + // They are substituted as is and do not require moving of classes. + if (fieldParametrisations.get(0) instanceof JDefinedClass) { + fieldParametrisationClass = (JDefinedClass) fieldParametrisations.get(0); + + ClassOutline fieldParametrisationClassOutline = interfaceImplementations.get(fieldParametrisationClass + .fullName()); + + if (fieldParametrisationClassOutline != null) { + assert fieldParametrisationClassOutline.ref == fieldParametrisationClass; + + fieldParametrisationImpl = fieldParametrisationClassOutline.implClass; + } else + fieldParametrisationImpl = fieldParametrisationClass; + } + + // We have a candidate class + Candidate candidate = new Candidate(candidateClass, field, fieldParametrisationClass, + fieldParametrisationImpl); + candidates.add(candidate); + + logger.debug("Candidate found: " + candidate.getClassName() + " [private " + + candidate.getFieldClass().name() + " " + candidate.getFieldName() + "]"); + } + + return candidates; + } + + /** + * Delete all candidate classes together with setter/getter methods and helper methods from + * ObjectFactory. + * + * @return the number of deletions performed + */ + private int deleteCandidates(Outline outline, Collection candidates) { + int deletionCount = 0; + + writeSummary("Deletions:"); + + // Visit all candidate classes. + for (Candidate candidate : candidates) { + // Only consider candidates that are actually included... + if (!isIncluded(candidate) || !candidate.isMarkedForRemoval()) + continue; + + // Get the defined class for candidate class. + JDefinedClass candidateClass = candidate.getCandidateClass(); + + deleteFactoryMethod(candidate.getValueObjectFactoryClass(), candidateClass); + deletionCount++; + + deleteClass(outline, candidateClass); + deletionCount++; + + // Redo the same for interface: + if (candidate.isValueObjectDisabled()) { + deleteFactoryMethod(candidate.getObjectFactoryClass(), candidateClass); + deletionCount++; + + for (Iterator iter = candidateClass._implements(); iter.hasNext();) { + JClass interfaceClass = iter.next(); + + if (!isHiddenClass(interfaceClass)) { + deleteClass(outline, (JDefinedClass) interfaceClass); + deletionCount++; + } + } + } + } + + return deletionCount; + } + + // + // Model factory manipulation helpers. + // + /** + * Rename methods in factory class: {@code createABC() -> createAC()}. + */ + private void renameFactoryMethod(JDefinedClass factoryClass, String oldMethodName, String newMethodName) { + for (JMethod method : factoryClass.methods()) { + String methodName = method.name(); + + if (!methodName.contains(oldMethodName)) + continue; + + method.name(methodName.replace(oldMethodName, newMethodName)); + + writeSummary("Renamed " + methodName + " -> " + method.name() + " in " + factoryClass.fullName()); + } + } + + /** + * Remove method {@code ObjectFactory} that creates an object of a given {@code clazz}. + * + * @return {@code true} is such method was successfully located and removed + */ + private boolean deleteFactoryMethod(JDefinedClass factoryClass, JDefinedClass clazz) { + for (Iterator iter = factoryClass.methods().iterator(); iter.hasNext();) { + JMethod method = iter.next(); + + // Remove the methods: + // * public T createT() { return new T(); } + // * public JAXBElement createT(T value) { return new JAXBElement(QNAME, T.class, null, value); } + // FIXME: The last case is mostly theoretical and live example is not known. + if ((method.type() instanceof JDefinedClass && ((JDefinedClass) method.type()).isAssignableFrom(clazz)) + || isListedAsParametrisation(clazz, method.type())) { + writeSummary("\tRemoving method " + method.type().fullName() + " " + method.name() + "() from " + + factoryClass.fullName()); + iter.remove(); + + return true; + } + } + + return false; + } + + // + // Model manipulation helpers. + // + /** + * Returns {@code true} if setter/getter with given public name was successfully removed from given class/interface. + */ + private boolean deleteSettersGetters(JDefinedClass clazz, String fieldPublicName) { + boolean result = false; + + for (Iterator iter = clazz.methods().iterator(); iter.hasNext();) { + JMethod m = iter.next(); + + if (m.name().equals("set" + fieldPublicName) || m.name().equals("get" + fieldPublicName)) { + iter.remove(); + result = true; + } + } + + return result; + } + + /** + * Move the given class to his grandparent (either class or package). + */ + private void moveClassLevelUp(Outline outline, JDefinedClass clazz) { + // Container can be a class or package: + JClassContainer container = clazz.parentContainer().parentContainer(); + setPrivateField(clazz, "outer", container); + + // FIXME: Pending https://java.net/jira/browse/JAXB-957 + if (container.isClass()) { + // Element class should be added as its container child: + JDefinedClass parentClass = (JDefinedClass) container; + + writeSummary("\tMoving inner class " + clazz.fullName() + " to class " + parentClass.fullName()); + + ((Map) getPrivateField(parentClass, "classes")).put(clazz.name(), clazz); + } else { + JPackage parentPackage = (JPackage) container; + + writeSummary("\tMoving inner class " + clazz.fullName() + " to package " + parentPackage.name()); + + ((Map) getPrivateField(parentPackage, "classes")).put(clazz.name(), clazz); + + // In this scenario class should have "static" modifier reset: + JMods mods = getPrivateField(clazz, "mods"); + setPrivateField(mods, "mods", mods.getValue() & ~JMod.STATIC); + + for (ClassOutline classOutline : outline.getClasses()) + if (classOutline.implClass == clazz) { + XSComponent sc = classOutline.target.getSchemaComponent(); + + // FIXME: Inner class is always a local declaration. + assert (sc instanceof XSDeclaration && ((XSDeclaration) sc).isLocal()); + + setPrivateField(sc, "anonymous", Boolean.FALSE); + } + } + } + + /** + * Remove the given class from it's parent class or package it is defined in. + */ + private void deleteClass(Outline outline, JDefinedClass clazz) { + if (clazz.parentContainer().isClass()) { + // The candidate class is an inner class. Remove the class from its parent class. + JDefinedClass parentClass = (JDefinedClass) clazz.parentContainer(); + + writeSummary("\tRemoving class " + clazz.fullName() + " from class " + parentClass.fullName()); + + for (Iterator iter = parentClass.classes(); iter.hasNext();) + if (iter.next().equals(clazz)) { + iter.remove(); + break; + } + } else { + // The candidate class is in a package. Remove the class from the package. + JPackage parentPackage = (JPackage) clazz.parentContainer(); + + writeSummary("\tRemoving class " + clazz.fullName() + " from package " + parentPackage.name()); + + parentPackage.remove(clazz); + + // And also remove the class from model. + for (Iterator iter = outline.getClasses().iterator(); iter.hasNext();) { + ClassOutline classOutline = iter.next(); + if (classOutline.implClass == clazz) { + outline.getModel().beans().remove(classOutline.target); + iter.remove(); + } + } + } + } + + /** + * Returns {@code true} if given class is a top of the class hierarchy like {@link Object} or {@link Serializable} or + * {@link JAXBElement}, or it is a customized super-class for all model beans. Basic JVM classes like {@link String} + * or {@link Integer} are not treated as top-classes: for them this method returns {@code false}. + */ + private static boolean isTopClass(JClass clazz) { + // We need a basis for narrowed class: + String className = clazz.erasure().fullName(); + + if ((className.equals(Object.class.getName()) || className.equals(Serializable.class.getName()) || className + .equals(JAXBElement.class.getName()))) + return true; + + // See also https://java.net/jira/browse/JAXB-958 + return clazz instanceof JDefinedClass && ((JDefinedClass) clazz).isHidden(); + } + + /** + * Returns {@code true} if given class is hidden, that is not generated & saved by XJC. These are for example + * instances of {@link JCodeModel.JReferencedClass} (JVM-wide classes) or instances of {@link JDefinedClass} with + * hidden flag (customized super-class or super-interface). + */ + static boolean isHiddenClass(JClass clazz) { + // See also https://java.net/jira/browse/JAXB-958 + return !(clazz instanceof JDefinedClass) || ((JDefinedClass) clazz).isHidden(); + } + + /** + * Returns + * true of the given + * type is {@link JClass} and contains + * classToCheck in the list of parametrisations. + */ + private static boolean isListedAsParametrisation(JClass classToCheck, JType type) { + return type instanceof JClass && ((JClass) type).getTypeParameters().contains(classToCheck); + } + + /** + * Apply the plural form if there are no customizations. Assuming that customization is correct as may define the + * plural form in more correct way, e.g. "fieldsOfScience" instead of "fieldOfSciences". + */ + private static boolean isPluralFormApplicable(FieldOutline field) { + // FIXME: It looks like customizations are always empty: + return applyPluralForm && field.getPropertyInfo().getCustomizations().isEmpty(); + } + + /** + * Returns the string value of passed argument. + */ + private static final String toString(JAnnotationValue generable) { + // There is hardly any clean universal way to get the value from e.g. JExpression except of serializing it. + // Compare JStringLiteral and JExp#dotclass(). + Writer w = new StringWriter(); + + generable.generate(new JFormatter(w)); + + // FIXME: Hopefully nobody will put quotes into annotation member value. + return w.toString().replace("\"", ""); + } + + // + // Annotation helpers. + // + /** + * For the given annotatable check that all annotations (and all annotations within annotations recursively) do not + * refer any candidate for removal. + */ + private void checkAnnotationReference(Map candidatesMap, JAnnotatable annotatable) { + List annotations; + if(annotatable instanceof JAnnotationArrayMember) + annotations = getPrivateField(annotatable,"values"); + else + annotations = getPrivateField(annotatable,"annotations"); + + if(annotations == null) return; + + for (JAnnotationUse annotation : annotations) { + String annotationClassName = XmlElementWrapperPlugin.getPrivateField(annotation, "clazz") .name(); + + if (annotationClassName.equals("XmlElementRefs") || annotationClassName.equals("XmlElements")) { + checkAnnotationReference(candidatesMap, + (JAnnotationArrayMember) getAnnotationMembers(annotation).get("value")); + + continue; + } + + // FIXME: Dirty workaround for http://java.net/jira/browse/JAXB-784: + if (!(annotationClassName.equals("XmlElementRef") || annotationClassName.equals("XmlElement"))) + continue; + + JAnnotationValue type = getAnnotationMemberExpression(annotation, "type"); + + if (type == null) + // Can be the case for @XmlElement(name = "publication-reference", namespace = "http://mycompany.org/exchange") + // or any other annotation without "type" + continue; + + String typeClassName = toString(type).replace(".class", ""); + + Candidate candidate = candidatesMap.get(typeClassName); + + if (candidate != null) { + logger.debug("Candidate " + candidate.getClassName() + + " is used in XmlElements/XmlElementRef and hence won't be removed."); + candidate.unmarkForRemoval(); + } + } + } + + /** + * Returns the value of the given annotation member of {@link XmlElement} annotation for the given field. + */ + private static JAnnotationValue getXmlElementMemberExpression(JVar field, String annotationMember) { + return getAnnotationMemberExpression(field, "XmlElement", annotationMember); + } + + /** + * Returns the value of the "value" member of {@link XmlJavaTypeAdapter} annotation for the given field. + */ + private static JAnnotationValue getXmlJavaTypeAdapterMemberExpression(JVar field) { + return getAnnotationMemberExpression(field, "XmlJavaTypeAdapter", "value"); + } + + /** + * Returns the value of the given annotation member of given annotation for the given field. + */ + private static JAnnotationValue getAnnotationMemberExpression(JVar field, String annotationClassName, String annotationMember) { + List annotations = getPrivateField(field,"annotations"); + if(annotations == null) return null; + + for (JAnnotationUse annotation : annotations) { + String className = XmlElementWrapperPlugin.getPrivateField(annotation, "clazz") .name(); + if (className.equals(annotationClassName)) + return getAnnotationMemberExpression(annotation, annotationMember); + } + + return null; + } + + /** + * Returns the string value of annotation element. For example, for annotation + * @XmlElementRef(name = "last-name", namespace = "http://mycompany.org/exchange", type = JAXBElement.class) + * for member name the value last-name will be returned. + */ + private static final JAnnotationValue getAnnotationMemberExpression(JAnnotationUse annotation, String annotationMember) { + Map memberValues = XmlElementWrapperPlugin.>getPrivateField(annotation, "memberValues"); + JAnnotationValue annotationValue = memberValues.get(annotationMember); + + if (annotationValue == null) + return null; + + return annotationValue; + } + + // + // Reflection helpers. + // + private static void setPrivateField(Object obj, String fieldName, Object newValue) { + setPrivateField(obj, obj.getClass(), fieldName, newValue); + } + + /** + * Set the {@code newValue} to private field {@code fieldName} of given object {@code obj}. + */ + private static void setPrivateField(Object obj, Class clazz, String fieldName, Object newValue) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, newValue); + } catch (NoSuchFieldException e) { + if (clazz.getSuperclass() == Object.class) + // Field is really not found: + throw new RuntimeException(e); + + // Try super class: + setPrivateField(obj, clazz.getSuperclass(), fieldName, newValue); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * Get the value of private field {@code fieldName} of given object {@code obj}. + */ + private static T getPrivateField(Object obj, String fieldName) { + try { + Field field = getField(obj.getClass(), fieldName); + field.setAccessible(true); + return (T) field.get(obj); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static Field getField(Class clazz, String fieldName) throws NoSuchFieldException { + try { + Field field = clazz.getDeclaredField(fieldName); + return field; + } catch (NoSuchFieldException ex) { + if(clazz.getSuperclass() == null) throw ex; + return getField(clazz.getSuperclass(), fieldName); + } + } + private static Map getAnnotationMembers(JAnnotationUse annotationUse) { + return XmlElementWrapperPlugin.>getPrivateField(annotationUse, "memberValues"); + } + + private static void addParam(JAnnotationUse annotationUse, String name, JAnnotationValue value) { + Map memberValues = getAnnotationMembers(annotationUse); + if(memberValues == null) { + memberValues = new LinkedHashMap(); + setPrivateField(annotationUse, "memberValues", memberValues); + } + memberValues.put(name, value); + } + + + // + // Includes / excludes support. + // + private boolean hasIncludes() { + return include != null; + } + + private boolean hasExcludes() { + return exclude != null; + } + + private boolean isIncluded(Candidate candidate) { + // + // A candidate is included if, ... + // 1. No includes and no excludes have been specified + // 2. Includes have been specified and candidate is included, and no excludes have been specified. + // 3. No includes have been specified and excludes have been specified and candidate is not in excludes. + // 4. Both includes and excludes have been specified and candidate is in includes and not in excludes. + // + if (!hasIncludes() && !hasExcludes()) + return true; // [+] (default) + else if (hasIncludes() && !hasExcludes()) + return include.contains(candidate.getClassName()); // [+/-] (included) + else if (!hasIncludes() && hasExcludes()) + return !exclude.contains(candidate.getClassName()); // [+/-] (excluded) + else + return include.contains(candidate.getClassName()) && !exclude.contains(candidate.getClassName()); // [+/-] (override) + } + + private String getIncludeOrExcludeReason() { + if (!hasIncludes() && !hasExcludes()) + return "(default)"; // [+] (default) + else if (hasIncludes() && !hasExcludes()) + return "(included)"; + else if (!hasIncludes() && hasExcludes()) + return "(excluded)"; + else + return "(override)"; + } + + /** + * Read all candidates from a given file into the given set. + */ + private static void readCandidates(File file, Set candidates) throws IOException { + BufferedReader input = new BufferedReader(new FileReader(file)); + String line; + + while ((line = input.readLine()) != null) { + line = line.trim(); + + // Lines starting with # are considered comments. + if (!line.startsWith("#")) + candidates.add(line); + } + + input.close(); + } + + // + // Logging helpers + // + private void writeSummary(String s) { + if (summary != null) + summary.println(s); + + logger.info(s); + } + + private void closeSummary() { + if (summary != null) + summary.close(); + } + + /** + * Types of collection instantiation modes. + */ + private enum Instantiation { + EARLY, LAZY, NONE + } + + /** + * Describes the collection container class -- a candidate for removal. + */ + private static class Candidate { + private JDefinedClass objectFactoryClass; + private final JDefinedClass valueObjectFactoryClass; + private final JDefinedClass candidateClass; + private final JFieldVar field; + private final JDefinedClass fieldParametrisationClass; + private final JDefinedClass fieldParametrisationImpl; + private boolean markedForRemoval = true; + + Candidate(JDefinedClass candidateClass, JFieldVar field, JDefinedClass fieldParametrizationClass, + JDefinedClass fieldParametrisationImpl) { + // If class has a non-hidden interface, then there is object factory in another package. + for (Iterator iter = candidateClass._implements(); iter.hasNext();) { + JClass interfaceClass = iter.next(); + + if (!isHiddenClass(interfaceClass)) { + objectFactoryClass = interfaceClass._package()._getClass(FACTORY_CLASS_NAME); + + if (objectFactoryClass != null) + break; + } + } + + this.valueObjectFactoryClass = candidateClass._package()._getClass(FACTORY_CLASS_NAME); + this.candidateClass = candidateClass; + this.field = field; + this.fieldParametrisationClass = fieldParametrizationClass; + this.fieldParametrisationImpl = fieldParametrisationImpl; + + assert objectFactoryClass != valueObjectFactoryClass; + } + + /** + * Object Factory class for interface classes. It's usually located in {@code impl.} subpackage relative to + * {@code valueObjectFactoryClass} package. May be {@code null}. + */ + public JDefinedClass getObjectFactoryClass() { + return objectFactoryClass; + } + + /** + * Object Factory class for value (implementation) classes. Is not {@code null}. + */ + public JDefinedClass getValueObjectFactoryClass() { + return valueObjectFactoryClass; + } + + /** + * Container class + */ + public JDefinedClass getCandidateClass() { + return candidateClass; + } + + /** + * Container class name + */ + public String getClassName() { + return candidateClass.fullName(); + } + + /** + * The only field in container class. + */ + public JFieldVar getField() { + return field; + } + + /** + * The name of the only field in container class. + */ + public String getFieldName() { + return field.name(); + } + + /** + * The class of the only field in container class. + */ + public JClass getFieldClass() { + return (JClass) field.type(); + } + + /** + * The only parametrisation class of the field. In case of basic parametrisation like {@link List} this + * property is {@code null}. + */ + public JDefinedClass getFieldParametrisationClass() { + return fieldParametrisationClass; + } + + /** + * If {@link #getFieldParametrisationClass()} is an interface, then this holds that same value. Otherwise it holds + * the implementation (value object) of {@link #getFieldParametrisationClass()}. In case of basic parametrisation + * like {@code List} this property is {@code null}. + */ + public JDefinedClass getFieldParametrisationImpl() { + return fieldParametrisationImpl; + } + + /** + * Returns {@code true} if the setting {@code } is active. + */ + public boolean isValueObjectDisabled() { + return objectFactoryClass != null; + } + + /** + * This flag controls if given candidate has green light to be removed. + */ + public boolean isMarkedForRemoval() { + return markedForRemoval; + } + + /** + * Signal that this candidate should not be removed from model on some reason. + */ + public void unmarkForRemoval() { + this.markedForRemoval = false; + } + + @Override + public String toString() { + return "Candidate[" + getClassName() + "]"; + } + } } diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/ObjectFactory.java deleted file mode 100644 index a121dd6..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/ObjectFactory.java +++ /dev/null @@ -1,119 +0,0 @@ - -package annotation_reference; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlElementDecl; -import javax.xml.bind.annotation.XmlRegistry; -import javax.xml.namespace.QName; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the annotation_reference package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static QName _Page_QNAME = new QName("", "page"); - private final static QName _Br_QNAME = new QName("", "br"); - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: annotation_reference - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Para } - * - */ - public Para createPara() { - return new Para(); - } - - /** - * Create an instance of {@link Markup } - * - */ - public Markup createMarkup() { - return new Markup(); - } - - /** - * Create an instance of {@link ClassesEu } - * - */ - public ClassesEu createClassesEu() { - return new ClassesEu(); - } - - /** - * Create an instance of {@link SearchMulti } - * - */ - public SearchMulti createSearchMulti() { - return new SearchMulti(); - } - - /** - * Create an instance of {@link ClassExt } - * - */ - public ClassExt createClassExt() { - return new ClassExt(); - } - - /** - * Create an instance of {@link SearchEu } - * - */ - public SearchEu createSearchEu() { - return new SearchEu(); - } - - /** - * Create an instance of {@link ClassCommon } - * - */ - public ClassCommon createClassCommon() { - return new ClassCommon(); - } - - /** - * Create an instance of {@link ClassesUs } - * - */ - public ClassesUs createClassesUs() { - return new ClassesUs(); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} - * - */ - @XmlElementDecl(namespace = "", name = "page") - public JAXBElement createPage(Object value) { - return new JAXBElement(_Page_QNAME, Object.class, null, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} - * - */ - @XmlElementDecl(namespace = "", name = "br") - public JAXBElement createBr(Object value) { - return new JAXBElement(_Br_QNAME, Object.class, null, value); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/SearchMulti.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/SearchMulti.java deleted file mode 100644 index 9973eaf..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/annotation_reference/SearchMulti.java +++ /dev/null @@ -1,75 +0,0 @@ - -package annotation_reference; - -import java.util.ArrayList; -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlType; - - -/** - *

Java class for search-multi complex type. - * - *

The following schema fragment specifies the expected content contained within this class. - * - *

- * <complexType name="search-multi">
- *   <complexContent>
- *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       <choice maxOccurs="unbounded">
- *         <element name="classes-eu" type="{}classes-eu"/>
- *         <element name="classes-us" type="{}classes-us"/>
- *       </choice>
- *     </restriction>
- *   </complexContent>
- * </complexType>
- * 
- * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "search-multi", propOrder = { - "classesEuOrClassesUs" -}) -public class SearchMulti { - - @XmlElements({ - @XmlElement(name = "classes-eu", type = ClassesEu.class), - @XmlElement(name = "classes-us", type = ClassesUs.class) - }) - protected List classesEuOrClassesUs; - - /** - * Gets the value of the classesEuOrClassesUs property. - * - *

- * This accessor method returns a reference to the live list, - * not a snapshot. Therefore any modification you make to the - * returned list will be present inside the JAXB object. - * This is why there is not a set method for the classesEuOrClassesUs property. - * - *

- * For example, to add a new item, do as follows: - *

-     *    getClassesEuOrClassesUs().add(newItem);
-     * 
- * - * - *

- * Objects of the following type(s) are allowed in the list - * {@link ClassesEu } - * {@link ClassesUs } - * - * - */ - public List getClassesEuOrClassesUs() { - if (classesEuOrClassesUs == null) { - classesEuOrClassesUs = new ArrayList(); - } - return this.classesEuOrClassesUs; - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/Entry.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/Entry.java index 213d289..d2e948b 100644 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/Entry.java +++ b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/Entry.java @@ -31,7 +31,7 @@ @XmlRootElement(name = "entry", namespace = "http://example.com/entry") public class Entry { - @XmlAttribute(name = "name") + @XmlAttribute @XmlSchemaType(name = "anySimpleType") protected String name; diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/ObjectFactory.java deleted file mode 100644 index a738850..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/different_namespaces/ObjectFactory.java +++ /dev/null @@ -1,48 +0,0 @@ - -package different_namespaces; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the different_namespaces package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: different_namespaces - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Container } - * - */ - public Container createContainer() { - return new Container(); - } - - /** - * Create an instance of {@link Entry } - * - */ - public Entry createEntry() { - return new Entry(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_as_parametrisation/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_as_parametrisation/ObjectFactory.java deleted file mode 100644 index b4f09b2..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_as_parametrisation/ObjectFactory.java +++ /dev/null @@ -1,64 +0,0 @@ - -package element_as_parametrisation; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the element_as_parametrisation package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: element_as_parametrisation - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Articles } - * - */ - public Articles createArticles() { - return new Articles(); - } - - /** - * Create an instance of {@link Article } - * - */ - public Article createArticle() { - return new Article(); - } - - /** - * Create an instance of {@link Publisher } - * - */ - public Publisher createPublisher() { - return new Publisher(); - } - - /** - * Create an instance of {@link ArticlesCollections } - * - */ - public ArticlesCollections createArticlesCollections() { - return new ArticlesCollections(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_referenced_twice/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_referenced_twice/ObjectFactory.java deleted file mode 100644 index 369337c..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_referenced_twice/ObjectFactory.java +++ /dev/null @@ -1,56 +0,0 @@ - -package element_referenced_twice; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the element_referenced_twice package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: element_referenced_twice - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link FamilyMember } - * - */ - public FamilyMember createFamilyMember() { - return new FamilyMember(); - } - - /** - * Create an instance of {@link Family } - * - */ - public Family createFamily() { - return new Family(); - } - - /** - * Create an instance of {@link FamilyMember.Id } - * - */ - public FamilyMember.Id createFamilyMemberId() { - return new FamilyMember.Id(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_with_parent/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_with_parent/ObjectFactory.java deleted file mode 100644 index 15b118d..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/element_with_parent/ObjectFactory.java +++ /dev/null @@ -1,56 +0,0 @@ - -package element_with_parent; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the element_with_parent package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: element_with_parent - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Group } - * - */ - public Group createGroup() { - return new Group(); - } - - /** - * Create an instance of {@link Organization } - * - */ - public Organization createOrganization() { - return new Organization(); - } - - /** - * Create an instance of {@link Group.Person } - * - */ - public Group.Person createGroupPerson() { - return new Group.Person(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element/ObjectFactory.java deleted file mode 100644 index dda832a..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element/ObjectFactory.java +++ /dev/null @@ -1,56 +0,0 @@ - -package inner_element; - -import javax.xml.bind.annotation.XmlRegistry; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the inner_element package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: inner_element - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Filesystem } - * - */ - public Filesystem createFilesystem() { - return new Filesystem(); - } - - /** - * Create an instance of {@link Volume } - * - */ - public Volume createVolume() { - return new Volume(); - } - - /** - * Create an instance of {@link Filesystem.FileItem } - * - */ - public Filesystem.FileItem createFilesystemFileItem() { - return new Filesystem.FileItem(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/ObjectFactory.java deleted file mode 100644 index 01a5d8d..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/ObjectFactory.java +++ /dev/null @@ -1,86 +0,0 @@ - -package inner_element_value_objects; - -import javax.xml.bind.annotation.XmlRegistry; -import inner_element_value_objects.impl.ArticleImpl; -import inner_element_value_objects.impl.ArticlesImpl; -import inner_element_value_objects.impl.FilesystemImpl; -import inner_element_value_objects.impl.PublisherImpl; -import inner_element_value_objects.impl.VolumeImpl; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the inner_element_value_objects package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - private final static Void _useJAXBProperties = null; - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: inner_element_value_objects - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Filesystem } - * - */ - public Filesystem createFilesystem() { - return new FilesystemImpl(); - } - - /** - * Create an instance of {@link Articles } - * - */ - public Articles createArticles() { - return new ArticlesImpl(); - } - - /** - * Create an instance of {@link Article } - * - */ - public Article createArticle() { - return new ArticleImpl(); - } - - /** - * Create an instance of {@link Publisher } - * - */ - public Publisher createPublisher() { - return new PublisherImpl(); - } - - /** - * Create an instance of {@link Volume } - * - */ - public Volume createVolume() { - return new VolumeImpl(); - } - - /** - * Create an instance of {@link Filesystem.FileItem } - * - */ - public Filesystem.FileItem createFilesystemFileItem() { - return new FilesystemImpl.FileItemImpl(); - } - -} diff --git a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/impl/ObjectFactory.java b/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/impl/ObjectFactory.java deleted file mode 100644 index 6683055..0000000 --- a/src/test/jaxb_resources/com/sun/tools/xjc/addon/xew/inner_element_value_objects/impl/ObjectFactory.java +++ /dev/null @@ -1,85 +0,0 @@ - -package inner_element_value_objects.impl; - -import javax.xml.bind.annotation.XmlRegistry; -import inner_element_value_objects.Article; -import inner_element_value_objects.Articles; -import inner_element_value_objects.Filesystem; -import inner_element_value_objects.Publisher; -import inner_element_value_objects.Volume; - - -/** - * This object contains factory methods for each - * Java content interface and Java element interface - * generated in the inner_element_value_objects.impl package. - *

An ObjectFactory allows you to programatically - * construct new instances of the Java representation - * for XML content. The Java representation of XML - * content can consist of schema derived interfaces - * and classes representing the binding of schema - * type definitions, element declarations and model - * groups. Factory methods for each of these are - * provided in this class. - * - */ -@XmlRegistry -public class ObjectFactory { - - - /** - * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: inner_element_value_objects.impl - * - */ - public ObjectFactory() { - } - - /** - * Create an instance of {@link Filesystem } - * - */ - public FilesystemImpl createFilesystem() { - return new FilesystemImpl(); - } - - /** - * Create an instance of {@link Articles } - * - */ - public ArticlesImpl createArticles() { - return new ArticlesImpl(); - } - - /** - * Create an instance of {@link Article } - * - */ - public ArticleImpl createArticle() { - return new ArticleImpl(); - } - - /** - * Create an instance of {@link Publisher } - * - */ - public PublisherImpl createPublisher() { - return new PublisherImpl(); - } - - /** - * Create an instance of {@link Volume } - * - */ - public VolumeImpl createVolume() { - return new VolumeImpl(); - } - - /** - * Create an instance of {@link Filesystem.FileItem } - * - */ - public FilesystemImpl.FileItemImpl createFilesystemFileItem() { - return new FilesystemImpl.FileItemImpl(); - } - -}