From 5818fd11a326e6a2f48abcb1626cf9c9dd56fe20 Mon Sep 17 00:00:00 2001 From: kmoore Date: Tue, 16 Nov 2010 19:45:44 +0000 Subject: refactored annotation container work to remove duplicate code --- .../java/source/SourceAnnotatedElement.java | 448 +++++++-------------- .../resource/java/source/SourceAnnotation.java | 289 +------------ .../internal/resource/java/source/SourceNode.java | 302 ++++++++++++++ .../java/source/SourceXmlSchemaAnnotation.java | 4 +- 4 files changed, 460 insertions(+), 583 deletions(-) diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotatedElement.java b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotatedElement.java index fe98dc8f69..69fa974fcc 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotatedElement.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotatedElement.java @@ -9,7 +9,6 @@ ******************************************************************************/ package org.eclipse.jpt.jaxb.core.internal.resource.java.source; -import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -19,12 +18,8 @@ import java.util.Set; import java.util.Vector; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MarkerAnnotation; -import org.eclipse.jdt.core.dom.MemberValuePair; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jpt.core.internal.utility.jdt.ASTNodeTextRange; @@ -39,7 +34,6 @@ import org.eclipse.jpt.utility.internal.CollectionTools; import org.eclipse.jpt.utility.internal.iterables.EmptyListIterable; import org.eclipse.jpt.utility.internal.iterables.ListIterable; import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable; -import org.eclipse.jpt.utility.internal.iterables.LiveCloneListIterable; /** * Java source annotated element (annotations) @@ -56,9 +50,11 @@ abstract class SourceAnnotatedElement final Vector annotations = new Vector(); /** - * Nestable annotations keyed on nestable annotation name + * Annotation containers keyed on nestable annotation name. + * This is used to store annotations that can be both standalone and nested + * and are moved back and forth between the 2. */ - final Map> nestableAnnotations = new HashMap>(); + final Map annotationContainers = new HashMap(); // ********** construction/initialization ********** @@ -68,164 +64,43 @@ abstract class SourceAnnotatedElement } public void initialize(CompilationUnit astRoot) { - this.annotatedElement.getBodyDeclaration(astRoot).accept(this.buildInitialAnnotationVisitor(astRoot)); + ASTNode node = this.annotatedElement.getBodyDeclaration(astRoot); + node.accept(this.buildInitialAnnotationVisitor(node)); } - private ASTVisitor buildInitialAnnotationVisitor(CompilationUnit astRoot) { - return new InitialAnnotationVisitor(astRoot, this.annotatedElement.getBodyDeclaration(astRoot)); + private ASTVisitor buildInitialAnnotationVisitor(ASTNode node) { + return new InitialAnnotationVisitor(node); } /** * called from {@link InitialAnnotationVisitor} */ - /* private */ void addInitialAnnotation(org.eclipse.jdt.core.dom.Annotation node, CompilationUnit astRoot) { + /* private */ void addInitialAnnotation(org.eclipse.jdt.core.dom.Annotation node) { String jdtAnnotationName = ASTTools.resolveAnnotation(node); if (jdtAnnotationName != null) { if (this.annotationIsValid(jdtAnnotationName)) { if (this.selectAnnotationNamed(this.annotations, jdtAnnotationName) == null) { // ignore duplicates Annotation annotation = this.buildAnnotation(jdtAnnotationName); - annotation.initialize(astRoot); + annotation.initialize((CompilationUnit) node.getRoot()); this.annotations.add(annotation); } } else if(this.annotationIsValidNestable(jdtAnnotationName)) { - Vector annotations = new Vector(); - NestableAnnotation annotation = this.buildNestableAnnotation(jdtAnnotationName, 0); - annotations.add(annotation); - annotation.initialize(astRoot); - this.nestableAnnotations.put(jdtAnnotationName, annotations); + AnnotationContainer container = new AnnotationContainer(jdtAnnotationName); + container.initializeNestableAnnotation(node); + this.annotationContainers.put(jdtAnnotationName, container); } else if(this.annotationIsValidContainer(jdtAnnotationName)) { String nestableAnnotationName = this.getNestableAnnotationName(jdtAnnotationName); - List nestedAnnotations = - this.getNestedAstAnnotations(node, this.getNestableElementName(nestableAnnotationName), nestableAnnotationName); - int index = 0; - Vector annotations = new Vector(); - for (org.eclipse.jdt.core.dom.Annotation nestedAstAnnotation : nestedAnnotations) { - NestableAnnotation annotation = this.buildNestableAnnotation(ASTTools.resolveAnnotation(nestedAstAnnotation), index++); - annotations.add(annotation); - annotation.initialize(astRoot); - } - this.nestableAnnotations.put(nestableAnnotationName, annotations); - } - } - } - - /** - * Return a list of the nested AST annotations. - */ - private ArrayList getNestedAstAnnotations(org.eclipse.jdt.core.dom.Annotation astContainerAnnotation, String elementName, String nestedAnnotationName) { - ArrayList result = new ArrayList(); - if (astContainerAnnotation == null || astContainerAnnotation.isMarkerAnnotation()) { - // no nested annotations - } - else if (astContainerAnnotation.isSingleMemberAnnotation()) { - if (elementName.equals("value")) { //$NON-NLS-1$ - Expression ex = ((SingleMemberAnnotation) astContainerAnnotation).getValue(); - addAstAnnotationsTo(ex, nestedAnnotationName, result); - } else { - // no nested annotations - } - } - else if (astContainerAnnotation.isNormalAnnotation()) { - MemberValuePair pair = this.getMemberValuePair((NormalAnnotation) astContainerAnnotation, elementName); - if (pair == null) { - // no nested annotations - } else { - addAstAnnotationsTo(pair.getValue(), nestedAnnotationName, result); - } - } - return result; - } - /** - * Add whatever annotations are represented by the specified expression to - * the specified list. Do not add null to the list for any non-annotation expression. - */ - private void addAstAnnotationsTo(Expression expression, String annotationName, ArrayList astAnnotations) { - if (expression == null) { - //do not add null to the list, not sure how we would get here... - } - else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) { - this.addAstAnnotationsTo((ArrayInitializer) expression, annotationName, astAnnotations); - } - else { - org.eclipse.jdt.core.dom.Annotation astAnnotation = getAstAnnotation_(expression, annotationName); - if (astAnnotation != null) { - astAnnotations.add(astAnnotation); - } - } - } - - private void addAstAnnotationsTo(ArrayInitializer arrayInitializer, String annotationName, ArrayList astAnnotations) { - List expressions = this.expressions(arrayInitializer); - for (Expression expression : expressions) { - org.eclipse.jdt.core.dom.Annotation astAnnotation = this.getAstAnnotation(expression, annotationName); - if (astAnnotation != null) { - astAnnotations.add(astAnnotation); + AnnotationContainer container = new AnnotationContainer(nestableAnnotationName); + container.initialize(node); + this.annotationContainers.put(nestableAnnotationName, container); } } } - // minimize scope of suppressed warnings - @SuppressWarnings("unchecked") - private List expressions(ArrayInitializer arrayInitializer) { - return arrayInitializer.expressions(); - } - - /** - * If the specified expression is an annotation with the specified name, return it; - * otherwise return null. - */ - private org.eclipse.jdt.core.dom.Annotation getAstAnnotation(Expression expression, String annotationName) { - // not sure how the expression could be null... - return (expression == null) ? null : getAstAnnotation_(expression, annotationName); - } - - /** - * pre-condition: expression is not null - */ - private org.eclipse.jdt.core.dom.Annotation getAstAnnotation_(Expression expression, String annotationName) { - switch (expression.getNodeType()) { - case ASTNode.NORMAL_ANNOTATION: - case ASTNode.SINGLE_MEMBER_ANNOTATION: - case ASTNode.MARKER_ANNOTATION: - org.eclipse.jdt.core.dom.Annotation astAnnotation = (org.eclipse.jdt.core.dom.Annotation) expression; - if (this.getQualifiedName(astAnnotation).equals(annotationName)) { - return astAnnotation; - } - return null; - default: - return null; - } - } - - private String getQualifiedName(org.eclipse.jdt.core.dom.Annotation astAnnotation) { - ITypeBinding typeBinding = astAnnotation.resolveTypeBinding(); - if (typeBinding != null) { - String resolvedName = typeBinding.getQualifiedName(); - if (resolvedName != null) { - return resolvedName; - } - } - return astAnnotation.getTypeName().getFullyQualifiedName(); - } - - private MemberValuePair getMemberValuePair(NormalAnnotation annotation, String elementName) { - List pairs = this.values(annotation); - for (MemberValuePair pair : pairs) { - if (pair.getName().getFullyQualifiedName().equals(elementName)) { - return pair; - } - } - return null; - } - - @SuppressWarnings("unchecked") - protected List values(NormalAnnotation na) { - return na.values(); - } public void synchronizeWith(CompilationUnit astRoot) { - this.syncAnnotations(astRoot); + this.syncAnnotations(this.annotatedElement.getBodyDeclaration(astRoot)); } @@ -249,23 +124,20 @@ abstract class SourceAnnotatedElement } public ListIterable getAnnotations(String nestableAnnotationName) { - List annotations = this.nestableAnnotations.get(nestableAnnotationName); - if (annotations != null) { - return new LiveCloneListIterable(annotations); - } - return EmptyListIterable.instance(); + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + return container != null ? container.getNestedAnnotations() : EmptyListIterable. instance(); } public int getAnnotationsSize(String nestableAnnotationName) { - List annotations = this.nestableAnnotations.get(nestableAnnotationName); - return annotations == null ? 0 : annotations.size(); + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + return container == null ? 0 : container.getNestedAnnotationsSize(); } public NestableAnnotation getAnnotation(int index, String nestableAnnotationName) { - List annotations = this.nestableAnnotations.get(nestableAnnotationName); - return annotations == null ? null : annotations.get(index); + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + return container == null ? null : container.nestedAnnotationAt(index); } - + private String getNestableAnnotationName(String containerAnnotationName) { return getAnnotationProvider().getNestableAnnotationName(containerAnnotationName); } @@ -291,50 +163,16 @@ abstract class SourceAnnotatedElement * and add a new nested annotation to it also */ public NestableAnnotation addAnnotation(int index, String nestableAnnotationName) { - List nestableAnnotations = this.nestableAnnotations.get(nestableAnnotationName); - if (nestableAnnotations == null) { - nestableAnnotations = new Vector(); - this.nestableAnnotations.put(nestableAnnotationName, nestableAnnotations); - } - //build the new nestable annotation at the end of the list then move it to the correct location. - int sourceIndex = this.getAnnotationsSize(nestableAnnotationName); - NestableAnnotation annotation = this.buildNestableAnnotation(nestableAnnotationName, sourceIndex); - nestableAnnotations.add(sourceIndex, annotation); - annotation.newAnnotation(); - this.moveAnnotation(index, sourceIndex, nestableAnnotationName); - return annotation; + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + if (container == null) { + container = new AnnotationContainer(nestableAnnotationName); + this.annotationContainers.put(nestableAnnotationName, container); + } + return container.addNestedAnnotation(index); } public void moveAnnotation(int targetIndex, int sourceIndex, String nestableAnnotationName) { - List nestedAnnotations = this.nestableAnnotations.get(nestableAnnotationName); - NestableAnnotation nestedAnnotation = nestedAnnotations.get(sourceIndex); - CollectionTools.move(nestedAnnotations, targetIndex, sourceIndex); - - this.syncAstAnnotationsAfterMove(targetIndex, sourceIndex, nestedAnnotations, nestedAnnotation); - } - - /** - * An annotation was moved within the specified annotation container from - * the specified source index to the specified target index. - * Synchronize the AST annotations with the resource model annotation container, - * starting with the lower index to prevent overlap. - */ - private void syncAstAnnotationsAfterMove(int targetIndex, int sourceIndex, List nestedAnnotations, NestableAnnotation nestedAnnotation) { - // move the Java annotation to the end of the list... - nestedAnnotation.moveAnnotation(nestedAnnotations.size()); - // ...then shift the other AST annotations over one slot... - List nestableAnnotations = CollectionTools.list(nestedAnnotations); - if (sourceIndex < targetIndex) { - for (int i = sourceIndex; i < targetIndex; i++) { - nestableAnnotations.get(i).moveAnnotation(i); - } - } else { - for (int i = sourceIndex; i > targetIndex; i-- ) { - nestableAnnotations.get(i).moveAnnotation(i); - } - } - // ...then move the AST annotation to the now empty slot at the target index - nestedAnnotation.moveAnnotation(targetIndex); + this.annotationContainers.get(nestableAnnotationName).moveNestedAnnotation(targetIndex, sourceIndex); } public void removeAnnotation(String annotationName) { @@ -350,24 +188,7 @@ abstract class SourceAnnotatedElement } public void removeAnnotation(int index, String nestableAnnotationName) { - NestableAnnotation nestableAnnotation = this.nestableAnnotations.get(nestableAnnotationName).remove(index); - nestableAnnotation.removeAnnotation(); - this.syncAstAnnotationsAfterRemove(index, this.nestableAnnotations.get(nestableAnnotationName)); - } - - /** - * An annotation was removed from the specified annotation container at the - * specified index. - * Synchronize the AST annotations with the resource model annotation container, - * starting at the specified index to prevent overlap. - */ - private void syncAstAnnotationsAfterRemove(int index, List nestedAnnotations) { - for (int i = index; i < nestedAnnotations.size(); i++) { - // the indices are the same because the model annotations are - // already in the proper locations - it's the AST annotations that - // need to be moved to the matching location - nestedAnnotations.get(i).moveAnnotation(i); - } + this.annotationContainers.get(nestableAnnotationName).removeNestedAnnotation(index); } private boolean annotationIsValid(String annotationName) { @@ -381,11 +202,11 @@ abstract class SourceAnnotatedElement private boolean annotationIsValidNestable(String annotationName) { return CollectionTools.contains(this.getValidNestableAnnotationNames(), annotationName); } - + Iterable getValidAnnotationNames() { return this.getAnnotationProvider().getAnnotationNames(); } - + Iterable getValidContainerAnnotationNames() { return this.getAnnotationProvider().getContainerAnnotationNames(); } @@ -393,59 +214,62 @@ abstract class SourceAnnotatedElement Iterable getValidNestableAnnotationNames() { return this.getAnnotationProvider().getNestableAnnotationNames(); } - + Annotation buildAnnotation(String annotationName) { return this.getAnnotationProvider().buildAnnotation(this, this.annotatedElement, annotationName); } - + Annotation buildNullAnnotation(String annotationName) { return this.getAnnotationProvider().buildNullAnnotation(this, annotationName); } - + NestableAnnotation buildNestableAnnotation(String annotationName, int index) { return this.getAnnotationProvider().buildAnnotation(this, this.annotatedElement, annotationName, index); } - private void syncAnnotations(CompilationUnit astRoot) { + private void syncAnnotations(ASTNode node) { HashSet annotationsToRemove = new HashSet(this.annotations); - HashSet nestableAnnotationsToRemove = new HashSet(); - for (List annotations : this.nestableAnnotations.values()) { - nestableAnnotationsToRemove.addAll(annotations); - } - this.annotatedElement.getBodyDeclaration(astRoot).accept(this.buildSynchronizeAnnotationVisitor(astRoot, annotationsToRemove, nestableAnnotationsToRemove)); + HashSet containersToRemove = new HashSet(this.annotationContainers.values()); + node.accept(this.buildSynchronizeAnnotationVisitor(node, annotationsToRemove, containersToRemove)); for (Annotation annotation : annotationsToRemove) { this.removeItemFromCollection(annotation, this.annotations, ANNOTATIONS_COLLECTION); } - for (NestableAnnotation nestableAnnotation : nestableAnnotationsToRemove) { - List list = this.nestableAnnotations.get(nestableAnnotation.getAnnotationName()); - list.remove(nestableAnnotation); - if (list.isEmpty()) { - this.nestableAnnotations.remove(nestableAnnotation.getAnnotationName()); + + for (AnnotationContainer annotationContainer : containersToRemove) { + this.annotationContainers.remove(annotationContainer.getNestedAnnotationName()); + fireItemsRemoved(NESTABLE_ANNOTATIONS_COLLECTION, CollectionTools.collection(annotationContainer.getNestedAnnotations())); + } + + Iterator keys = this.annotationContainers.keySet().iterator(); + + while (keys.hasNext()) { + String annotationName = keys.next(); + if (this.annotationContainers.get(annotationName).getNestedAnnotationsSize() == 0) { + keys.remove(); } - this.fireItemRemoved(NESTABLE_ANNOTATIONS_COLLECTION, nestableAnnotation); } } - private ASTVisitor buildSynchronizeAnnotationVisitor(CompilationUnit astRoot, Set annotationsToRemove, Set nestableAnnotationsToRemove) { - return new SynchronizeAnnotationVisitor(astRoot, this.annotatedElement.getBodyDeclaration(astRoot), annotationsToRemove, nestableAnnotationsToRemove); + private ASTVisitor buildSynchronizeAnnotationVisitor(ASTNode node, Set annotationsToRemove, Set containersToRemove) { + return new SynchronizeAnnotationVisitor(node, annotationsToRemove, containersToRemove); } /** * called from {@link SynchronizeAnnotationVisitor} */ - /* private */ void addOrSyncAnnotation(org.eclipse.jdt.core.dom.Annotation node, CompilationUnit astRoot, Set annotationsToRemove, Set nestableAnnotationsToRemove) { + /* private */ void addOrSyncAnnotation(org.eclipse.jdt.core.dom.Annotation node, Set annotationsToRemove, Set containersToRemove) { String jdtAnnotationName = ASTTools.resolveAnnotation(node); if (jdtAnnotationName != null) { if (this.annotationIsValid(jdtAnnotationName)) { - this.addOrSyncAnnotation_(jdtAnnotationName, astRoot, annotationsToRemove); + this.addOrSyncAnnotation_(node, jdtAnnotationName, annotationsToRemove); } else if(this.annotationIsValidNestable(jdtAnnotationName)) { - this.addOrSyncNestableAnnotation_(jdtAnnotationName, astRoot, nestableAnnotationsToRemove); + this.addOrSyncNestableAnnotation_(node, jdtAnnotationName, containersToRemove); } else if(this.annotationIsValidContainer(jdtAnnotationName)) { - this.addOrSyncContainerAnnotation_(node, jdtAnnotationName, astRoot, nestableAnnotationsToRemove); + this.addOrSyncContainerAnnotation_(node, jdtAnnotationName, containersToRemove); } } } @@ -453,14 +277,14 @@ abstract class SourceAnnotatedElement /** * pre-condition: jdtAnnotationName is valid */ - private void addOrSyncAnnotation_(String jdtAnnotationName, CompilationUnit astRoot, Set annotationsToRemove) { + private void addOrSyncAnnotation_(org.eclipse.jdt.core.dom.Annotation node, String jdtAnnotationName, Set annotationsToRemove) { Annotation annotation = this.selectAnnotationNamed(annotationsToRemove, jdtAnnotationName); if (annotation != null) { - annotation.synchronizeWith(astRoot); + annotation.synchronizeWith((CompilationUnit) node.getRoot()); annotationsToRemove.remove(annotation); } else { annotation = this.buildAnnotation(jdtAnnotationName); - annotation.initialize(astRoot); + annotation.initialize((CompilationUnit) node.getRoot()); this.addItemToCollection(annotation, this.annotations, ANNOTATIONS_COLLECTION); } } @@ -468,74 +292,43 @@ abstract class SourceAnnotatedElement /** * pre-condition: jdtAnnotationName is valid */ - private void addOrSyncNestableAnnotation_(String jdtAnnotationName, CompilationUnit astRoot, Set annotationsToRemove) { - List nestableAnnotations = this.nestableAnnotations.get(jdtAnnotationName); - if (nestableAnnotations != null) { - if (nestableAnnotations.size() > 1) { - //ignore the new standalone annotation as a container annotation already exists - } - else if (nestableAnnotations.size() == 1) { - nestableAnnotations.get(0).synchronizeWith(astRoot); - annotationsToRemove.remove(nestableAnnotations.get(0)); - } + private void addOrSyncNestableAnnotation_(org.eclipse.jdt.core.dom.Annotation node, String nestableAnnotationName, Set containersToRemove) { + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + if (container != null) { + container.synchronizeNestableAnnotation(node); + containersToRemove.remove(container); } else { - nestableAnnotations = new Vector(); - NestableAnnotation annotation = this.buildNestableAnnotation(jdtAnnotationName, 0); - annotation.initialize(astRoot); - this.nestableAnnotations.put(jdtAnnotationName, nestableAnnotations); - this.fireItemAdded(NESTABLE_ANNOTATIONS_COLLECTION, annotation); + container = new AnnotationContainer(nestableAnnotationName); + container.initializeNestableAnnotation(node); + this.annotationContainers.put(nestableAnnotationName, container); + this.fireItemAdded(NESTABLE_ANNOTATIONS_COLLECTION, container.nestedAnnotationAt(0)); } } /** * pre-condition: node is valid container annotation */ - private void addOrSyncContainerAnnotation_(org.eclipse.jdt.core.dom.Annotation node, String containerAnnotationName, CompilationUnit astRoot, Set annotationsToRemove) { + private void addOrSyncContainerAnnotation_(org.eclipse.jdt.core.dom.Annotation node, String containerAnnotationName, Set containersToRemove) { String nestableAnnotationName = this.getNestableAnnotationName(containerAnnotationName); - List nestedAstAnnotations = - this.getNestedAstAnnotations(node, this.getNestableElementName(nestableAnnotationName), nestableAnnotationName); - List nestedAnnotations = this.nestableAnnotations.get(nestableAnnotationName); - if (nestedAnnotations == null) { - nestedAnnotations = new Vector(); - int index = 0; - for (org.eclipse.jdt.core.dom.Annotation nestedAstAnnotation : nestedAstAnnotations) { - NestableAnnotation annotation = this.buildNestableAnnotation(ASTTools.resolveAnnotation(nestedAstAnnotation), index++); - annotation.initialize(astRoot); - nestedAnnotations.add(annotation); - } - this.nestableAnnotations.put(nestableAnnotationName, nestedAnnotations); - this.fireItemsAdded(NESTABLE_ANNOTATIONS_COLLECTION, nestedAnnotations); + AnnotationContainer container = this.annotationContainers.get(nestableAnnotationName); + if (container == null) { + container = new AnnotationContainer(nestableAnnotationName); + container.initialize(node); + this.annotationContainers.put(nestableAnnotationName, container); + this.fireItemsAdded(NESTABLE_ANNOTATIONS_COLLECTION, CollectionTools.collection(container.getNestedAnnotations())); } else { - Iterator astAnnotationStream = nestedAstAnnotations.iterator(); - Iterator nestedAnnotationsStream = nestedAnnotations.iterator(); - int index = 0; - while (nestedAnnotationsStream.hasNext()) { - index++; - NestableAnnotation nestedAnnotation = nestedAnnotationsStream.next(); - if (astAnnotationStream.hasNext()) { - // matching AST annotation is present - synchronize the nested annotation - astAnnotationStream.next(); // maybe someday we can pass this to the update - nestedAnnotation.synchronizeWith(astRoot); - annotationsToRemove.remove(nestedAnnotation); - } - } - while (astAnnotationStream.hasNext()) { - NestableAnnotation nestedAnnotation = this.buildNestableAnnotation(ASTTools.resolveAnnotation(astAnnotationStream.next()), index++); - nestedAnnotation.initialize(astRoot); - nestedAnnotations.add(nestedAnnotation); - this.fireItemAdded(NESTABLE_ANNOTATIONS_COLLECTION, nestedAnnotation); - } + container.synchronize(node); + containersToRemove.remove(container); } } - // ********** miscellaneous ********** public boolean isAnnotated() { - return ! this.annotations.isEmpty() || ! this.nestableAnnotations.isEmpty(); + return ! this.annotations.isEmpty() || ! this.annotationContainers.isEmpty(); } public TextRange getTextRange(CompilationUnit astRoot) { @@ -572,13 +365,11 @@ abstract class SourceAnnotatedElement protected static abstract class AnnotationVisitor extends ASTVisitor { - protected final CompilationUnit astRoot; protected final ASTNode node; - protected AnnotationVisitor(CompilationUnit astRoot, ASTNode node) { + protected AnnotationVisitor(ASTNode node) { super(); - this.astRoot = astRoot; this.node = node; } @@ -615,13 +406,13 @@ abstract class SourceAnnotatedElement protected class InitialAnnotationVisitor extends AnnotationVisitor { - protected InitialAnnotationVisitor(CompilationUnit astRoot, ASTNode node) { - super(astRoot, node); + protected InitialAnnotationVisitor(ASTNode node) { + super(node); } @Override protected void visitChildAnnotation(org.eclipse.jdt.core.dom.Annotation node) { - SourceAnnotatedElement.this.addInitialAnnotation(node, this.astRoot); + SourceAnnotatedElement.this.addInitialAnnotation(node); } } @@ -633,18 +424,77 @@ abstract class SourceAnnotatedElement extends AnnotationVisitor { protected final Set annotationsToRemove; + protected final Set containersToRemove; - protected final Set nestableAnnotationsToRemove; - - protected SynchronizeAnnotationVisitor(CompilationUnit astRoot, ASTNode node, Set annotationsToRemove, Set nestableAnnotationsToRemove) { - super(astRoot, node); + protected SynchronizeAnnotationVisitor(ASTNode node, Set annotationsToRemove, Set containersToRemove) { + super(node); this.annotationsToRemove = annotationsToRemove; - this.nestableAnnotationsToRemove = nestableAnnotationsToRemove; + this.containersToRemove = containersToRemove; } @Override protected void visitChildAnnotation(org.eclipse.jdt.core.dom.Annotation node) { - SourceAnnotatedElement.this.addOrSyncAnnotation(node, this.astRoot, this.annotationsToRemove, this.nestableAnnotationsToRemove); + SourceAnnotatedElement.this.addOrSyncAnnotation(node, this.annotationsToRemove, this.containersToRemove); + } + } + + + class AnnotationContainer extends SourceNode.AnnotationContainer + { + private final String nestableAnnotationName; + + protected AnnotationContainer(String nestableAnnotationName) { + super(); + this.nestableAnnotationName = nestableAnnotationName; + } + + /** + * Return the element name of the nested annotations + */ + @Override + protected String getElementName() { + return SourceAnnotatedElement.this.getNestableElementName(this.nestableAnnotationName); + } + + /** + * Return the nested annotation name + */ + @Override + protected String getNestedAnnotationName() { + return this.nestableAnnotationName; + } + + /** + * Return a new nested annotation at the given index + */ + @Override + protected NestableAnnotation buildNestedAnnotation(int index) { + return SourceAnnotatedElement.this.buildNestableAnnotation(this.nestableAnnotationName, index); + } + + public void initializeNestableAnnotation(org.eclipse.jdt.core.dom.Annotation standaloneNestableAnnotation) { + NestableAnnotation nestedAnnotation = this.buildNestedAnnotation(0); + this.nestedAnnotations.add(nestedAnnotation); + nestedAnnotation.initialize((CompilationUnit) standaloneNestableAnnotation.getRoot()); + } + + public void synchronizeNestableAnnotation(org.eclipse.jdt.core.dom.Annotation standaloneNestableAnnotation) { + if (this.getNestedAnnotationsSize() > 1) { + //ignore the new standalone annotation as a container annotation already exists + } + else if (this.getNestedAnnotationsSize() == 1) { + this.nestedAnnotationAt(0).synchronizeWith((CompilationUnit) standaloneNestableAnnotation.getRoot()); + } + } + + @Override + protected void fireItemAdded(int index, NestableAnnotation nestedAnnotation) { + SourceAnnotatedElement.this.fireItemAdded(NESTABLE_ANNOTATIONS_COLLECTION, nestedAnnotation); + } + + @Override + protected void fireItemsRemoved(int index, List removedItems) { + SourceAnnotatedElement.this.fireItemsRemoved(NESTABLE_ANNOTATIONS_COLLECTION, removedItems); } } } diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotation.java b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotation.java index 6796fb56f5..3e22f27d4c 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotation.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceAnnotation.java @@ -9,18 +9,9 @@ ******************************************************************************/ package org.eclipse.jpt.jaxb.core.internal.resource.java.source; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Vector; import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.MemberValuePair; -import org.eclipse.jdt.core.dom.NormalAnnotation; -import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jpt.core.internal.utility.jdt.ASTNodeTextRange; import org.eclipse.jpt.core.internal.utility.jdt.ElementAnnotationAdapter; import org.eclipse.jpt.core.utility.TextRange; @@ -31,10 +22,6 @@ import org.eclipse.jpt.core.utility.jdt.DeclarationAnnotationElementAdapter; import org.eclipse.jpt.jaxb.core.resource.java.Annotation; import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceNode; import org.eclipse.jpt.jaxb.core.resource.java.NestableAnnotation; -import org.eclipse.jpt.utility.internal.CollectionTools; -import org.eclipse.jpt.utility.internal.StringTools; -import org.eclipse.jpt.utility.internal.iterables.ListIterable; -import org.eclipse.jpt.utility.internal.iterables.LiveCloneListIterable; /** * some common state and behavior for Java source annotations; @@ -164,10 +151,8 @@ public abstract class SourceAnnotation * needs to call initialize(CompilationUnit) on it. * @param the type of the resource nestable annotations */ - abstract class AnnotationContainer + abstract class AnnotationContainer extends SourceNode.AnnotationContainer { - private final Vector nestedAnnotations = new Vector(); - protected AnnotationContainer() { super(); } @@ -177,274 +162,14 @@ public abstract class SourceAnnotation */ protected abstract String getAnnotationsPropertyName(); - /** - * Return the element name of the nested annotations - */ - protected abstract String getElementName(); - - /** - * Return the nested annotation name - */ - protected abstract String getNestedAnnotationName(); - - /** - * Return a new nested annotation at the given index - */ - protected abstract T buildNestedAnnotation(int index); - - public void initialize(CompilationUnit astRoot) { - // ignore the nested AST annotations themselves - // (maybe someday we can use them during initialization...) - int size = this.getNestedAstAnnotations(astRoot).size(); - for (int i = 0; i < size; i++) { - T nestedAnnotation = this.buildNestedAnnotation(i); - this.nestedAnnotations.add(i, nestedAnnotation); - nestedAnnotation.initialize(astRoot); - } - } - - /** - * Synchronize the resource model annotations with those in the specified AST. - * Trigger the appropriate change notification. - */ - public void synchronize(CompilationUnit astRoot) { - ArrayList astAnnotations = this.getNestedAstAnnotations(astRoot); - Iterator astAnnotationStream = astAnnotations.iterator(); - - for (T nestedAnnotation : this.getNestedAnnotations()) { - if (astAnnotationStream.hasNext()) { - // matching AST annotation is present - synchronize the nested annotation - astAnnotationStream.next(); // maybe someday we can pass this to the update - nestedAnnotation.synchronizeWith(astRoot); - } else { - // no more AST annotations - remove the remaining nested annotations and exit - this.syncRemoveNestedAnnotations(astAnnotations.size()); - return; - } - } - - // add nested annotations for any remaining AST annotations - while (astAnnotationStream.hasNext()) { - this.syncAddNestedAnnotation(astAnnotationStream.next()); - } - } - - public ListIterable getNestedAnnotations() { - return new LiveCloneListIterable(this.nestedAnnotations); - } - - public int getNestedAnnotationsSize() { - return this.nestedAnnotations.size(); - } - - public T nestedAnnotationAt(int index) { - return this.nestedAnnotations.get(index); - } - - public T addNestedAnnotation(int index) { - // add a new annotation to the end of the list... - int sourceIndex = this.getNestedAnnotationsSize(); - T nestedAnnotation = this.buildNestedAnnotation(sourceIndex); - this.nestedAnnotations.add(sourceIndex, nestedAnnotation); - nestedAnnotation.newAnnotation(); - // ...then move it to the specified index - this.moveNestedAnnotation(index, sourceIndex); - return nestedAnnotation; - } - - public T moveNestedAnnotation(int targetIndex, int sourceIndex) { - if (targetIndex != sourceIndex) { - return this.moveNestedAnnotation_(targetIndex, sourceIndex); - } - return null; - } - - public T removeNestedAnnotation(int index) { - T nestedAnnotation = this.nestedAnnotations.remove(index); - nestedAnnotation.removeAnnotation(); - this.syncAstAnnotationsAfterRemove(index); - return nestedAnnotation; - } - - private T moveNestedAnnotation_(int targetIndex, int sourceIndex) { - T nestedAnnotation = CollectionTools.move(this.nestedAnnotations, targetIndex, sourceIndex).get(targetIndex); - this.syncAstAnnotationsAfterMove(targetIndex, sourceIndex, nestedAnnotation); - return nestedAnnotation; - } - - /** - * Return a list of the nested AST annotations. - */ - private ArrayList getNestedAstAnnotations(CompilationUnit astRoot) { - ArrayList result = new ArrayList(); - org.eclipse.jdt.core.dom.Annotation astContainerAnnotation = this.getAstAnnotation(astRoot); - if (astContainerAnnotation == null || astContainerAnnotation.isMarkerAnnotation()) { - // no nested annotations - } - else if (astContainerAnnotation.isSingleMemberAnnotation()) { - if (this.getElementName().equals("value")) { //$NON-NLS-1$ - Expression ex = ((SingleMemberAnnotation) astContainerAnnotation).getValue(); - this.addAstAnnotationsTo(ex, result); - } else { - // no nested annotations - } - } - else if (astContainerAnnotation.isNormalAnnotation()) { - MemberValuePair pair = this.getMemberValuePair((NormalAnnotation) astContainerAnnotation); - if (pair == null) { - // no nested annotations - } else { - this.addAstAnnotationsTo(pair.getValue(), result); - } - } - return result; - } - - /** - * Add whatever annotations are represented by the specified expression to - * the specified list. Do not add null to the list for any non-annotation expression. - */ - private void addAstAnnotationsTo(Expression expression, ArrayList astAnnotations) { - if (expression == null) { - //do not add null to the list, not sure how we would get here... - } - else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) { - this.addAstAnnotationsTo((ArrayInitializer) expression, astAnnotations); - } - else { - org.eclipse.jdt.core.dom.Annotation astAnnotation = this.getAstAnnotation_(expression); - if (astAnnotation != null) { - astAnnotations.add(astAnnotation); - } - } - } - - private void addAstAnnotationsTo(ArrayInitializer arrayInitializer, ArrayList astAnnotations) { - List expressions = this.expressions(arrayInitializer); - for (Expression expression : expressions) { - org.eclipse.jdt.core.dom.Annotation astAnnotation = getAstAnnotation(expression); - if (astAnnotation != null) { - astAnnotations.add(astAnnotation); - } - } - } - - // minimize scope of suppressed warnings - @SuppressWarnings("unchecked") - private List expressions(ArrayInitializer arrayInitializer) { - return arrayInitializer.expressions(); - } - - private org.eclipse.jdt.core.dom.Annotation getAstAnnotation(CompilationUnit astRoot) { - return SourceAnnotation.this.getAstAnnotation(astRoot); - } - - /** - * If the specified expression is an annotation with the specified name, return it; - * otherwise return null. - */ - private org.eclipse.jdt.core.dom.Annotation getAstAnnotation(Expression expression) { - // not sure how the expression could be null... - return (expression == null) ? null : getAstAnnotation_(expression); - } - - /** - * pre-condition: expression is not null - */ - private org.eclipse.jdt.core.dom.Annotation getAstAnnotation_(Expression expression) { - switch (expression.getNodeType()) { - case ASTNode.NORMAL_ANNOTATION: - case ASTNode.SINGLE_MEMBER_ANNOTATION: - case ASTNode.MARKER_ANNOTATION: - org.eclipse.jdt.core.dom.Annotation astAnnotation = (org.eclipse.jdt.core.dom.Annotation) expression; - if (this.getQualifiedName(astAnnotation).equals(this.getNestedAnnotationName())) { - return astAnnotation; - } - return null; - default: - return null; - } - } - - private String getQualifiedName(org.eclipse.jdt.core.dom.Annotation astAnnotation) { - ITypeBinding typeBinding = astAnnotation.resolveTypeBinding(); - if (typeBinding != null) { - String resolvedName = typeBinding.getQualifiedName(); - if (resolvedName != null) { - return resolvedName; - } - } - return astAnnotation.getTypeName().getFullyQualifiedName(); - } - - private MemberValuePair getMemberValuePair(NormalAnnotation annotation) { - List pairs = this.values(annotation); - for (MemberValuePair pair : pairs) { - if (pair.getName().getFullyQualifiedName().equals(this.getElementName())) { - return pair; - } - } - return null; + @Override + protected void fireItemAdded(int index, T addedItem) { + SourceAnnotation.this.fireItemAdded(this.getAnnotationsPropertyName(), index, addedItem); } - @SuppressWarnings("unchecked") - protected List values(NormalAnnotation na) { - return na.values(); - } - - /** - * An annotation was moved within the specified annotation container from - * the specified source index to the specified target index. - * Synchronize the AST annotations with the resource model annotation container, - * starting with the lower index to prevent overlap. - */ - private void syncAstAnnotationsAfterMove(int targetIndex, int sourceIndex, T nestedAnnotation) { - // move the Java annotation to the end of the list... - nestedAnnotation.moveAnnotation(this.getNestedAnnotationsSize()); - // ...then shift the other AST annotations over one slot... - if (sourceIndex < targetIndex) { - for (int i = sourceIndex; i < targetIndex; i++) { - this.nestedAnnotations.get(i).moveAnnotation(i); - } - } else { - for (int i = sourceIndex; i > targetIndex; i-- ) { - this.nestedAnnotations.get(i).moveAnnotation(i); - } - } - // ...then move the AST annotation to the now empty slot at the target index - nestedAnnotation.moveAnnotation(targetIndex); - } - - /** - * An annotation was removed from the specified annotation container at the - * specified index. - * Synchronize the AST annotations with the resource model annotation container, - * starting at the specified index to prevent overlap. - */ - private void syncAstAnnotationsAfterRemove(int index) { - for (int i = index; i < this.getNestedAnnotationsSize(); i++) { - // the indices are the same because the model annotations are - // already in the proper locations - it's the AST annotations that - // need to be moved to the matching location - this.nestedAnnotations.get(i).moveAnnotation(i); - } - } - - private void syncAddNestedAnnotation(org.eclipse.jdt.core.dom.Annotation astAnnotation) { - int index = this.getNestedAnnotationsSize(); - T nestedAnnotation = this.buildNestedAnnotation(index); - nestedAnnotation.initialize((CompilationUnit) astAnnotation.getRoot()); - this.nestedAnnotations.add(index, nestedAnnotation); - SourceAnnotation.this.fireItemAdded(this.getAnnotationsPropertyName(), index, nestedAnnotation); - } - - private void syncRemoveNestedAnnotations(int index) { - SourceAnnotation.this.removeItemsFromList(index, this.nestedAnnotations, this.getAnnotationsPropertyName()); - } - @Override - public String toString() { - return StringTools.buildToStringFor(this); - } + protected void fireItemsRemoved(int index, java.util.List removedItems) { + SourceAnnotation.this.fireItemsRemoved(this.getAnnotationsPropertyName(), index, removedItems); + } } } diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceNode.java b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceNode.java index 7928586649..4217dbde2e 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceNode.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceNode.java @@ -9,8 +9,25 @@ ******************************************************************************/ package org.eclipse.jpt.jaxb.core.internal.resource.java.source; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ArrayInitializer; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.MemberValuePair; +import org.eclipse.jdt.core.dom.NormalAnnotation; +import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceCompilationUnit; import org.eclipse.jpt.jaxb.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.jaxb.core.resource.java.NestableAnnotation; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterables.ListIterable; +import org.eclipse.jpt.utility.internal.iterables.LiveCloneListIterable; /** @@ -28,4 +45,289 @@ public abstract class SourceNode return (JavaResourceCompilationUnit) this.getRoot(); } + /** + * A container for nested annotations. The owner of the AnnotationContainer + * needs to call initialize(org.eclipse.jdt.core.dom.Annotation) on it. + * @param the type of the resource nestable annotations + */ + abstract class AnnotationContainer + { + protected final Vector nestedAnnotations = new Vector(); + + protected AnnotationContainer() { + super(); + } + + /** + * Return the element name of the nested annotations + */ + protected abstract String getElementName(); + + /** + * Return the nested annotation name + */ + protected abstract String getNestedAnnotationName(); + + /** + * Return a new nested annotation at the given index + */ + protected abstract T buildNestedAnnotation(int index); + + protected abstract void fireItemAdded(int index, T nestedAnnotation); + + protected abstract void fireItemsRemoved(int index, List removedItems); + + protected void initialize(org.eclipse.jdt.core.dom.Annotation astContainerAnnotation) { + // ignore the nested AST annotations themselves + // (maybe someday we can use them during initialization...) + int size = this.getNestedAstAnnotations(astContainerAnnotation).size(); + for (int i = 0; i < size; i++) { + T nestedAnnotation = this.buildNestedAnnotation(i); + this.nestedAnnotations.add(i, nestedAnnotation); + nestedAnnotation.initialize((CompilationUnit) astContainerAnnotation.getRoot()); + } + } + + /** + * Synchronize the resource model annotations with those in the specified AST. + * Trigger the appropriate change notification. + */ + protected void synchronize(org.eclipse.jdt.core.dom.Annotation astContainerAnnotation) { + ArrayList astAnnotations = this.getNestedAstAnnotations(astContainerAnnotation); + Iterator astAnnotationStream = astAnnotations.iterator(); + + for (T nestedAnnotation : this.getNestedAnnotations()) { + if (astAnnotationStream.hasNext()) { + // matching AST annotation is present - synchronize the nested annotation + astAnnotationStream.next(); // maybe someday we can pass this to the update + nestedAnnotation.synchronizeWith((CompilationUnit) astContainerAnnotation.getRoot()); + } else { + // no more AST annotations - remove the remaining nested annotations and exit + this.syncRemoveNestedAnnotations(astAnnotations.size()); + return; + } + } + + // add nested annotations for any remaining AST annotations + while (astAnnotationStream.hasNext()) { + this.syncAddNestedAnnotation(astAnnotationStream.next()); + } + } + + public ListIterable getNestedAnnotations() { + return new LiveCloneListIterable(this.nestedAnnotations); + } + + public int getNestedAnnotationsSize() { + return this.nestedAnnotations.size(); + } + + public T nestedAnnotationAt(int index) { + return this.nestedAnnotations.get(index); + } + + public T addNestedAnnotation(int index) { + // add a new annotation to the end of the list... + int sourceIndex = this.getNestedAnnotationsSize(); + T nestedAnnotation = this.buildNestedAnnotation(sourceIndex); + this.nestedAnnotations.add(sourceIndex, nestedAnnotation); + nestedAnnotation.newAnnotation(); + // ...then move it to the specified index + this.moveNestedAnnotation(index, sourceIndex); + return nestedAnnotation; + } + + public T moveNestedAnnotation(int targetIndex, int sourceIndex) { + if (targetIndex != sourceIndex) { + return this.moveNestedAnnotation_(targetIndex, sourceIndex); + } + return null; + } + + public T removeNestedAnnotation(int index) { + T nestedAnnotation = this.nestedAnnotations.remove(index); + nestedAnnotation.removeAnnotation(); + this.syncAstAnnotationsAfterRemove(index); + return nestedAnnotation; + } + + private T moveNestedAnnotation_(int targetIndex, int sourceIndex) { + T nestedAnnotation = CollectionTools.move(this.nestedAnnotations, targetIndex, sourceIndex).get(targetIndex); + this.syncAstAnnotationsAfterMove(targetIndex, sourceIndex, nestedAnnotation); + return nestedAnnotation; + } + + /** + * Return a list of the nested AST annotations. + */ + private ArrayList getNestedAstAnnotations(org.eclipse.jdt.core.dom.Annotation astContainerAnnotation) { + ArrayList result = new ArrayList(); + if (astContainerAnnotation == null || astContainerAnnotation.isMarkerAnnotation()) { + // no nested annotations + } + else if (astContainerAnnotation.isSingleMemberAnnotation()) { + if (this.getElementName().equals("value")) { //$NON-NLS-1$ + Expression ex = ((SingleMemberAnnotation) astContainerAnnotation).getValue(); + this.addAstAnnotationsTo(ex, result); + } else { + // no nested annotations + } + } + else if (astContainerAnnotation.isNormalAnnotation()) { + MemberValuePair pair = this.getMemberValuePair((NormalAnnotation) astContainerAnnotation); + if (pair == null) { + // no nested annotations + } else { + this.addAstAnnotationsTo(pair.getValue(), result); + } + } + return result; + } + + /** + * Add whatever annotations are represented by the specified expression to + * the specified list. Do not add null to the list for any non-annotation expression. + */ + private void addAstAnnotationsTo(Expression expression, ArrayList astAnnotations) { + if (expression == null) { + //do not add null to the list, not sure how we would get here... + } + else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) { + this.addAstAnnotationsTo((ArrayInitializer) expression, astAnnotations); + } + else { + org.eclipse.jdt.core.dom.Annotation astAnnotation = this.getAstAnnotation_(expression); + if (astAnnotation != null) { + astAnnotations.add(astAnnotation); + } + } + } + + private void addAstAnnotationsTo(ArrayInitializer arrayInitializer, ArrayList astAnnotations) { + List expressions = this.expressions(arrayInitializer); + for (Expression expression : expressions) { + org.eclipse.jdt.core.dom.Annotation astAnnotation = getAstAnnotation(expression); + if (astAnnotation != null) { + astAnnotations.add(astAnnotation); + } + } + } + + // minimize scope of suppressed warnings + @SuppressWarnings("unchecked") + private List expressions(ArrayInitializer arrayInitializer) { + return arrayInitializer.expressions(); + } + + /** + * If the specified expression is an annotation with the specified name, return it; + * otherwise return null. + */ + private org.eclipse.jdt.core.dom.Annotation getAstAnnotation(Expression expression) { + // not sure how the expression could be null... + return (expression == null) ? null : getAstAnnotation_(expression); + } + + /** + * pre-condition: expression is not null + */ + private org.eclipse.jdt.core.dom.Annotation getAstAnnotation_(Expression expression) { + switch (expression.getNodeType()) { + case ASTNode.NORMAL_ANNOTATION: + case ASTNode.SINGLE_MEMBER_ANNOTATION: + case ASTNode.MARKER_ANNOTATION: + org.eclipse.jdt.core.dom.Annotation astAnnotation = (org.eclipse.jdt.core.dom.Annotation) expression; + if (this.getQualifiedName(astAnnotation).equals(this.getNestedAnnotationName())) { + return astAnnotation; + } + return null; + default: + return null; + } + } + + private String getQualifiedName(org.eclipse.jdt.core.dom.Annotation astAnnotation) { + ITypeBinding typeBinding = astAnnotation.resolveTypeBinding(); + if (typeBinding != null) { + String resolvedName = typeBinding.getQualifiedName(); + if (resolvedName != null) { + return resolvedName; + } + } + return astAnnotation.getTypeName().getFullyQualifiedName(); + } + + private MemberValuePair getMemberValuePair(NormalAnnotation annotation) { + List pairs = this.values(annotation); + for (MemberValuePair pair : pairs) { + if (pair.getName().getFullyQualifiedName().equals(this.getElementName())) { + return pair; + } + } + return null; + } + + @SuppressWarnings("unchecked") + protected List values(NormalAnnotation na) { + return na.values(); + } + + /** + * An annotation was moved within the specified annotation container from + * the specified source index to the specified target index. + * Synchronize the AST annotations with the resource model annotation container, + * starting with the lower index to prevent overlap. + */ + private void syncAstAnnotationsAfterMove(int targetIndex, int sourceIndex, T nestedAnnotation) { + // move the Java annotation to the end of the list... + nestedAnnotation.moveAnnotation(this.getNestedAnnotationsSize()); + // ...then shift the other AST annotations over one slot... + if (sourceIndex < targetIndex) { + for (int i = sourceIndex; i < targetIndex; i++) { + this.nestedAnnotations.get(i).moveAnnotation(i); + } + } else { + for (int i = sourceIndex; i > targetIndex; i-- ) { + this.nestedAnnotations.get(i).moveAnnotation(i); + } + } + // ...then move the AST annotation to the now empty slot at the target index + nestedAnnotation.moveAnnotation(targetIndex); + } + + /** + * An annotation was removed from the specified annotation container at the + * specified index. + * Synchronize the AST annotations with the resource model annotation container, + * starting at the specified index to prevent overlap. + */ + private void syncAstAnnotationsAfterRemove(int index) { + for (int i = index; i < this.getNestedAnnotationsSize(); i++) { + // the indices are the same because the model annotations are + // already in the proper locations - it's the AST annotations that + // need to be moved to the matching location + this.nestedAnnotations.get(i).moveAnnotation(i); + } + } + + protected void syncAddNestedAnnotation(org.eclipse.jdt.core.dom.Annotation astAnnotation) { + int index = this.getNestedAnnotationsSize(); + T nestedAnnotation = this.buildNestedAnnotation(index); + nestedAnnotation.initialize((CompilationUnit) astAnnotation.getRoot()); + this.nestedAnnotations.add(index, nestedAnnotation); + this.fireItemAdded(index, nestedAnnotation); + } + + protected void syncRemoveNestedAnnotations(int index) { + List subList = this.nestedAnnotations.subList(index, this.getNestedAnnotationsSize()); + List removedItems = new ArrayList(subList); + subList.clear(); + this.fireItemsRemoved(index, removedItems); + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this); + } + } } diff --git a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceXmlSchemaAnnotation.java b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceXmlSchemaAnnotation.java index f5c8853a53..a78decaf31 100644 --- a/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceXmlSchemaAnnotation.java +++ b/jaxb/plugins/org.eclipse.jpt.jaxb.core/src/org/eclipse/jpt/jaxb/core/internal/resource/java/source/SourceXmlSchemaAnnotation.java @@ -108,7 +108,7 @@ public class SourceXmlSchemaAnnotation this.elementFormDefault = buildElementFormDefault(astRoot); this.location = buildLocation(astRoot); this.namespace = buildNamespace(astRoot); - this.xmlnsContainer.initialize(astRoot); + this.xmlnsContainer.initialize(this.getAstAnnotation(astRoot)); } public void synchronizeWith(CompilationUnit astRoot) { @@ -116,7 +116,7 @@ public class SourceXmlSchemaAnnotation syncElementFormDefault(buildElementFormDefault(astRoot)); syncLocation(buildLocation(astRoot)); syncNamespace(buildNamespace(astRoot)); - this.xmlnsContainer.synchronize(astRoot); + this.xmlnsContainer.synchronize(this.getAstAnnotation(astRoot)); } @Override -- cgit v1.2.3