Skip to content

Commit

Permalink
If moving of inner class to parent collides with another class, its n…
Browse files Browse the repository at this point in the history
…ame is prepended with candidate class name (fixes #39).
  • Loading branch information
dmak committed Mar 11, 2015
1 parent e04ef86 commit 785cb1b
Show file tree
Hide file tree
Showing 8 changed files with 579 additions and 27 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ You can find more examples of this plugin in [`samples`](samples/) directory (in

## What's new

### v1.5 (future release)

* Bugs fixed ([#39](https://github.com/dmak/jaxb-xew-plugin/issues/39), [#40](https://github.com/dmak/jaxb-xew-plugin/issues/32), [#33](https://github.com/dmak/jaxb-xew-plugin/issues/40)).

### v1.4

* Bugs fixed ([#21](https://github.com/dmak/jaxb-xew-plugin/issues/21), [#32](https://github.com/dmak/jaxb-xew-plugin/issues/32), [#33](https://github.com/dmak/jaxb-xew-plugin/issues/33)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,14 @@ private void runInternal(Outline outline) throws IOException, ClassNotFoundExcep

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()) && !isHiddenClass(fieldType)) {
if (fieldType.isAssignableFrom(c.getClazz()) && !isHiddenClass(fieldType)) {
// If the given field has type T, it cannot be also in the list of parametrisations (e.g. T<T>).
candidate = c;
break;
}
// If the candidate T is referred from list of parametrisations (e.g. List<T>), it cannot be removed.
// However field substitutions will take place.
else if (isListedAsParametrisation(c.getCandidateClass(), fieldType)) {
else if (isListedAsParametrisation(c.getClazz(), fieldType)) {
logger.debug("Candidate " + c.getClassName() + " is listed as parametrisation of "
+ targetClass.fullName() + "#" + fieldName + " and hence won't be removed.");
c.unmarkForRemoval();
Expand Down Expand Up @@ -705,11 +705,11 @@ && deleteSettersGetters((JDefinedClass) interfaceClass, propertyName)) {
}

/**
* 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<br>
* {@code TopClass -> ContainerClass (marked for removal) -> ElementClass}<br>
* If candidate class contains the inner class which is collection parametrisation (type), then this inner class has
* to be moved to top class. For example from<br>
* {@code TypeClass (is a collection type) -> ContainerClass (marked for removal) -> ElementClass}<br>
* we need to get<br>
* {@code TopClass (will have a collection) -> ElementClass}.<br>
* {@code TypeClass -> ElementClass}.<br>
* Also this move should be reflected on factory method names.
*/
private boolean moveInnerClassToParent(Outline outline, Candidate candidate) {
Expand All @@ -720,7 +720,8 @@ private boolean moveInnerClassToParent(Outline outline, Candidate candidate) {

JDefinedClass fieldParametrisationImpl = candidate.getFieldParametrisationImpl();

if (candidate.getCandidateClass() != fieldParametrisationImpl.parentContainer()) {
if (candidate.getClazz() != fieldParametrisationImpl.parentContainer()) {
// Field parametrisation class is not inner class of the candidate:
return false;
}

Expand Down Expand Up @@ -975,7 +976,7 @@ private int deleteCandidates(Outline outline, Collection<Candidate> candidates)
}

// Get the defined class for candidate class.
JDefinedClass candidateClass = candidate.getCandidateClass();
JDefinedClass candidateClass = candidate.getClazz();

deletionCount += deleteFactoryMethod(candidate.getValueObjectFactoryClass(), candidate);

Expand Down Expand Up @@ -1038,8 +1039,8 @@ private int deleteFactoryMethod(JDefinedClass factoryClass, Candidate candidate)
// * @XmlElementDecl(..., scope = X.class)
// public JAXBElement<T> createT...(T value) { return new JAXBElement<...>(QNAME, T.class, X.class, value); }
if ((method.type() instanceof JDefinedClass && ((JDefinedClass) method.type()).isAssignableFrom(candidate
.getCandidateClass()))
|| isListedAsParametrisation(candidate.getCandidateClass(), method.type())
.getClazz()))
|| isListedAsParametrisation(candidate.getClazz(), method.type())
|| candidate.getScopedElementInfos().containsKey(method.name())) {
writeSummary("\tRemoving factory method [" + method.type().fullName() + "#" + method.name()
+ "()] from " + factoryClass.fullName());
Expand Down Expand Up @@ -1075,30 +1076,32 @@ private boolean deleteSettersGetters(JDefinedClass clazz, String fieldPublicName
}

/**
* Move the given class to his grandparent (either class or package).
* Move the given class to his grandparent (either class or package). The given {@code clazz} should be inner class.
*/
@SuppressWarnings("unchecked")
private void moveClassLevelUp(Outline outline, JDefinedClass clazz) {
// Modify the container so it now refers the class. Container can be a class or package.
JClassContainer container = clazz.parentContainer().parentContainer();
JDefinedClass parent = (JDefinedClass) clazz.parentContainer();
JClassContainer grandParent = parent.parentContainer();
Map<String, JDefinedClass> classes;

// FIXME: Pending https://java.net/jira/browse/JAXB-957
if (container.isClass()) {
if (grandParent.isClass()) {
// Element class should be added as its container child:
JDefinedClass parentClass = (JDefinedClass) container;
JDefinedClass grandParentClass = (JDefinedClass) grandParent;

writeSummary("\tMoving inner class " + clazz.fullName() + " to class " + parentClass.fullName());
writeSummary("\tMoving inner class " + clazz.fullName() + " to class " + grandParentClass.fullName());

((Map<String, JDefinedClass>) getPrivateField(parentClass, "classes")).put(clazz.name(), clazz);
classes = ((Map<String, JDefinedClass>) getPrivateField(grandParentClass, "classes"));
}
else {
JPackage parentPackage = (JPackage) container;
JPackage grandParentPackage = (JPackage) grandParent;

writeSummary("\tMoving inner class " + clazz.fullName() + " to package " + parentPackage.name());
writeSummary("\tMoving inner class " + clazz.fullName() + " to package " + grandParentPackage.name());

((Map<String, JDefinedClass>) getPrivateField(parentPackage, "classes")).put(clazz.name(), clazz);
classes = ((Map<String, JDefinedClass>) getPrivateField(grandParentPackage, "classes"));

// In this scenario class should have "static" modifier reset:
// In this scenario class should have "static" modifier reset otherwise it won't compile:
setPrivateField(clazz.mods(), "mods", Integer.valueOf(clazz.mods().getValue() & ~JMod.STATIC));

for (ClassOutline classOutline : outline.getClasses()) {
Expand All @@ -1109,12 +1112,21 @@ private void moveClassLevelUp(Outline outline, JDefinedClass clazz) {
assert (sc instanceof XSDeclaration && ((XSDeclaration) sc).isLocal());

setPrivateField(sc, "anonymous", Boolean.FALSE);

break;
}
}
}

if (classes.containsKey(clazz.name())) {
writeSummary("\tRenaming class " + clazz.fullName() + " to class " + parent.name() + clazz.name());
setPrivateField(clazz, "name", parent.name() + clazz.name());
}

classes.put(clazz.name(), clazz);

// Finally modify the class so that it refers back the container:
setPrivateField(clazz, "outer", container);
setPrivateField(clazz, "outer", grandParent);
}

/**
Expand Down Expand Up @@ -1307,7 +1319,7 @@ private static class Candidate {
/**
* Container class
*/
public JDefinedClass getCandidateClass() {
public JDefinedClass getClazz() {
return candidateClass;
}

Expand All @@ -1319,7 +1331,7 @@ public String getClassName() {
}

/**
* The only field in container class.
* The only field in container class (collection property).
*/
public JFieldVar getField() {
return field;
Expand All @@ -1333,7 +1345,7 @@ public String getFieldName() {
}

/**
* The class of the only field in container class.
* The class of the only field in container class (collection interface or concrete implementation).
*/
public JClass getFieldClass() {
return (JClass) field.type();
Expand All @@ -1347,15 +1359,15 @@ public String getFieldTargetNamespace() {
}

/**
* The only parametrisation class of the field. In case of basic parametrisation like {@link List<String>} this
* property is {@code null}.
* The only parametrisation class of the field (collection type). In case of basic parametrisation like
* {@link List<String>} this property is {@code null}.
*/
public JDefinedClass getFieldParametrisationClass() {
return fieldParametrisationClass;
}

/**
* If {@link #getFieldParametrisationClass()} is an interface, then this holds that same value. Otherwise it
* If {@link #getFieldParametrisationClass()} is an interface, then this holds the same value. Otherwise it
* holds the implementation (value object) of {@link #getFieldParametrisationClass()}. In case of basic
* parametrisation like {@code List<String>} this property is {@code null}.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

package element_name_collision;

import javax.xml.bind.annotation.XmlRegistry;


/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the element_name_collision package.
* <p>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_name_collision
*
*/
public ObjectFactory() {
}

/**
* Create an instance of {@link Root }
*
*/
public Root createRoot() {
return new Root();
}

/**
* Create an instance of {@link Root.Action }
*
*/
public Root.Action createRootAction() {
return new Root.Action();
}

/**
* Create an instance of {@link Root.Action.AddItem }
*
*/
public Root.Action.AddItem createRootActionAddItem() {
return new Root.Action.AddItem();
}

/**
* Create an instance of {@link Root.Action.Item }
*
*/
public Root.Action.Item createRootActionItem() {
return new Root.Action.Item();
}

}
Loading

0 comments on commit 785cb1b

Please sign in to comment.