blob: d296b00eb4875f01b951ec7440a7b45b0868e518 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2011 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.resource.java.source;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
import org.eclipse.jpt.common.core.internal.utility.jdt.JDTType;
import org.eclipse.jpt.common.core.utility.jdt.Type;
import org.eclipse.jpt.common.utility.MethodSignature;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.SimpleIntReference;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
import org.eclipse.jpt.common.utility.internal.iterators.TreeIterator;
import org.eclipse.jpt.jpa.core.internal.jpa2.resource.java.GeneratedAnnotationDefinition;
import org.eclipse.jpt.jpa.core.internal.jpa2.resource.java.StaticMetamodelAnnotationDefinition;
import org.eclipse.jpt.jpa.core.jpa2.resource.java.GeneratedAnnotation;
import org.eclipse.jpt.jpa.core.jpa2.resource.java.JavaResourcePersistentType2_0;
import org.eclipse.jpt.jpa.core.jpa2.resource.java.StaticMetamodelAnnotation;
import org.eclipse.jpt.jpa.core.resource.java.AccessType;
import org.eclipse.jpt.jpa.core.resource.java.Annotation;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourceCompilationUnit;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
/**
* Java source persistent type
*/
final class SourcePersistentType
extends SourcePersistentMember<Type>
implements JavaResourcePersistentType2_0
{
private String name;
private String qualifiedName;
private String packageName;
private String superclassQualifiedName;
private String declaringTypeName;
private boolean abstract_; // 'abstract' is a reserved word
private boolean static_; // 'static' is a reserved word
private boolean memberType;
private boolean hasPrivateNoArgConstructor;
private boolean hasNoArgConstructor;
private final Vector<JavaResourcePersistentType> types = new Vector<JavaResourcePersistentType>();
private final Vector<JavaResourcePersistentAttribute> fields = new Vector<JavaResourcePersistentAttribute>();
private final Vector<JavaResourcePersistentAttribute> methods = new Vector<JavaResourcePersistentAttribute>();
private StaticMetamodelAnnotation staticMetamodelAnnotation;
//TODO move to interface after maintenance
public static final String STATIC_METAMODEL_ANNOTATION_PROPERTY = "staticMetamodelAnnotation"; //$NON-NLS-1$
private GeneratedAnnotation generatedAnnotation;
//TODO move to interface after maintenance
public static final String GENERATED_ANNOTATION_PROPERTY = "generatedAnnotation"; //$NON-NLS-1$
private static final StaticMetamodelAnnotationDefinition STATIC_METAMODEL_ANNOTATION_DEFINITION = StaticMetamodelAnnotationDefinition.instance();
private static final GeneratedAnnotationDefinition GENERATED_ANNOTATION_DEFINITION = GeneratedAnnotationDefinition.instance();
// ********** construction/initialization **********
/**
* build top-level persistent type
*/
static JavaResourcePersistentType newInstance(
JavaResourceCompilationUnit javaResourceCompilationUnit,
TypeDeclaration typeDeclaration,
CompilationUnit astRoot) {
Type type = new JDTType(
typeDeclaration,
javaResourceCompilationUnit.getCompilationUnit(),
javaResourceCompilationUnit.getModifySharedDocumentCommandExecutor(),
javaResourceCompilationUnit.getAnnotationEditFormatter());
JavaResourcePersistentType jrpt = new SourcePersistentType(javaResourceCompilationUnit, type);
jrpt.initialize(astRoot);
return jrpt;
}
/**
* build nested persistent type
*/
private static JavaResourcePersistentType newInstance(
JavaResourceCompilationUnit javaResourceCompilationUnit,
Type declaringType,
TypeDeclaration typeDeclaration,
int occurrence,
CompilationUnit astRoot) {
Type type = new JDTType(
declaringType,
typeDeclaration,
occurrence,
javaResourceCompilationUnit.getCompilationUnit(),
javaResourceCompilationUnit.getModifySharedDocumentCommandExecutor(),
javaResourceCompilationUnit.getAnnotationEditFormatter());
JavaResourcePersistentType jrpt = new SourcePersistentType(javaResourceCompilationUnit, type);
jrpt.initialize(astRoot);
return jrpt;
}
private SourcePersistentType(JavaResourceCompilationUnit javaResourceCompilationUnit, Type type) {
super(javaResourceCompilationUnit, type);
}
@Override
public void initialize(CompilationUnit astRoot) {
super.initialize(astRoot);
ITypeBinding binding = this.annotatedElement.getBinding(astRoot);
this.name = this.buildName(binding);
this.qualifiedName = this.buildQualifiedName(binding);
this.packageName = this.buildPackageName(binding);
this.superclassQualifiedName = this.buildSuperclassQualifiedName(binding);
this.declaringTypeName = this.buildDeclaringTypeName(binding);
this.abstract_ = this.buildAbstract(binding);
this.static_ = this.buildStatic(binding);
this.memberType = this.buildMemberType(binding);
this.hasNoArgConstructor = this.buildHasNoArgConstructor(binding);
this.hasPrivateNoArgConstructor = this.buildHasPrivateNoArgConstructor(binding);
this.initializeTypes(astRoot);
this.initializeFields(astRoot);
this.initializeMethods(astRoot);
}
/**
* Handle the <code>StaticMetamodel</code> and <code>Generated</code>
* annotations differently, since they are not really JPA "mapping"
* annotations....
*/
@Override
void addInitialAnnotation(String astAnnotationName, CompilationUnit astRoot) {
if (astAnnotationName.equals(STATIC_METAMODEL_ANNOTATION_DEFINITION.getAnnotationName())) {
this.addInitialStaticMetamodelAnnotation(astRoot);
} else if (astAnnotationName.equals(GENERATED_ANNOTATION_DEFINITION.getAnnotationName())) {
this.addInitialGeneratedAnnotation(astRoot);
} else {
super.addInitialAnnotation(astAnnotationName, astRoot);
}
}
// ********** update **********
@Override
public void synchronizeWith(CompilationUnit astRoot) {
super.synchronizeWith(astRoot);
ITypeBinding binding = this.annotatedElement.getBinding(astRoot);
this.syncName(this.buildName(binding));
this.syncQualifiedName(this.buildQualifiedName(binding));
this.syncPackageName(this.buildPackageName(binding));
this.syncSuperclassQualifiedName(this.buildSuperclassQualifiedName(binding));
this.syncDeclaringTypeName(this.buildDeclaringTypeName(binding));
this.syncAbstract(this.buildAbstract(binding));
this.syncStatic(this.buildStatic(binding));
this.syncMemberType(this.buildMemberType(binding));
this.syncHasNoArgConstructor(this.buildHasNoArgConstructor(binding));
this.syncHasPrivateNoArgConstructor(this.buildHasPrivateNoArgConstructor(binding));
this.syncTypes(astRoot);
this.syncFields(astRoot);
this.syncMethods(astRoot);
this.syncMetamodelAnnotations(astRoot);
}
/**
* Handle the <code>StaticMetamodel</code> and <code>Generated</code>
* annotations differently, since they are not really JPA "mapping"
* annotations. We aren't overriding {@link #addOrSyncAnnotation(String, CompilationUnit, java.util.Set)}
* because we also have to handle removing these annotations separately.
*/
private void syncMetamodelAnnotations(CompilationUnit astRoot) {
ITypeBinding binding = this.annotatedElement.getBinding(astRoot);
if (binding != null) {
this.syncStaticMetamodelAnnotation(astRoot, binding);
this.syncGeneratedAnnotation(astRoot, binding);
}
}
// ********** SourcePersistentMember implementation **********
@Override
Iterator<String> validAnnotationNames() {
return this.getAnnotationProvider().typeAnnotationNames();
}
@Override
Annotation buildAnnotation(String annotationName) {
return this.getAnnotationProvider().buildTypeAnnotation(this, this.annotatedElement, annotationName);
}
@Override
Annotation buildNullAnnotation(String annotationName) {
return this.getAnnotationProvider().buildNullTypeAnnotation(this, annotationName);
}
@Override
public void resolveTypes(CompilationUnit astRoot) {
super.resolveTypes(astRoot);
this.syncSuperclassQualifiedName(this.buildSuperclassQualifiedName(this.annotatedElement.getBinding(astRoot)));
for (JavaResourcePersistentAttribute field : this.getFields()) {
field.resolveTypes(astRoot);
}
// a new type can trigger a method parameter type to be a resolved,
// fully-qualified name, so we need to rebuild our list of methods:
// "setFoo(Foo)" is not the same as "setFoo(com.bar.Foo)"
// and, vice-versa, a removed type can "unresolve" a parameter type
this.syncMethods(astRoot);
for (JavaResourcePersistentAttribute method : this.getMethods()) {
method.resolveTypes(astRoot);
}
for (JavaResourcePersistentType type : this.getTypes()) {
type.resolveTypes(astRoot);
}
}
@Override
public void toString(StringBuilder sb) {
sb.append(this.name);
}
// ******** JavaResourcePersistentType implementation ********
// ***** name
public String getName() {
return this.name;
}
private void syncName(String astName) {
String old = this.name;
this.name = astName;
this.firePropertyChanged(NAME_PROPERTY, old, astName);
}
private String buildName(ITypeBinding binding) {
return (binding == null) ? null : binding.getName();
}
// ***** qualified name
public String getQualifiedName() {
return this.qualifiedName;
}
private void syncQualifiedName(String astQualifiedName) {
String old = this.qualifiedName;
this.qualifiedName = astQualifiedName;
this.firePropertyChanged(QUALIFIED_NAME_PROPERTY, old, astQualifiedName);
}
private String buildQualifiedName(ITypeBinding binding) {
return (binding == null) ? null : binding.getQualifiedName();
}
// ***** package name
public String getPackageName() {
return this.packageName;
}
private void syncPackageName(String astPackageName) {
String old = this.packageName;
this.packageName = astPackageName;
this.firePropertyChanged(PACKAGE_NAME_PROPERTY, old, astPackageName);
}
private String buildPackageName(ITypeBinding binding) {
return (binding == null) ? null : binding.getPackage().getName();
}
// ***** superclass qualified name
public String getSuperclassQualifiedName() {
return this.superclassQualifiedName;
}
private void syncSuperclassQualifiedName(String astSuperclassQualifiedName) {
String old = this.superclassQualifiedName;
this.superclassQualifiedName = astSuperclassQualifiedName;
this.firePropertyChanged(SUPERCLASS_QUALIFIED_NAME_PROPERTY, old, astSuperclassQualifiedName);
}
private String buildSuperclassQualifiedName(ITypeBinding binding) {
if (binding == null) {
return null;
}
ITypeBinding superclass = binding.getSuperclass();
return (superclass == null) ? null : superclass.getTypeDeclaration().getQualifiedName();
}
// ***** package
public boolean isIn(IPackageFragment packageFragment) {
return StringTools.stringsAreEqual(packageFragment.getElementName(), this.packageName);
}
// ***** declaring type name
public String getDeclaringTypeName() {
return this.declaringTypeName;
}
private void syncDeclaringTypeName(String astDeclaringTypeName) {
String old = this.declaringTypeName;
this.declaringTypeName = astDeclaringTypeName;
this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, astDeclaringTypeName);
}
private String buildDeclaringTypeName(ITypeBinding binding) {
if (binding == null) {
return null;
}
ITypeBinding declaringClass = binding.getDeclaringClass();
return (declaringClass == null) ? null : declaringClass.getTypeDeclaration().getQualifiedName();
}
// ***** abstract
public boolean isAbstract() {
return this.abstract_;
}
private void syncAbstract(boolean astAbstract) {
boolean old = this.abstract_;
this.abstract_ = astAbstract;
this.firePropertyChanged(ABSTRACT_PROPERTY, old, astAbstract);
}
private boolean buildAbstract(ITypeBinding binding) {
return (binding == null) ? false : Modifier.isAbstract(binding.getModifiers());
}
// ***** static
public boolean isStatic() {
return this.static_;
}
private void syncStatic(boolean astStatic_) {
boolean old = this.static_;
this.static_ = astStatic_;
this.firePropertyChanged(STATIC_PROPERTY, old, astStatic_);
}
private boolean buildStatic(ITypeBinding binding) {
return (binding == null) ? false : Modifier.isStatic(binding.getModifiers());
}
// ***** member type
public boolean isMemberType() {
return this.memberType;
}
private void syncMemberType(boolean astMemberType) {
boolean old = this.memberType;
this.memberType = astMemberType;
this.firePropertyChanged(MEMBER_TYPE_PROPERTY, old, astMemberType);
}
private boolean buildMemberType(ITypeBinding binding) {
return (binding == null) ? false : binding.isMember();
}
// ***** no-arg constructor
public boolean hasNoArgConstructor() {
return this.hasNoArgConstructor;
}
private void syncHasNoArgConstructor(boolean astHasNoArgConstructor) {
boolean old = this.hasNoArgConstructor;
this.hasNoArgConstructor = astHasNoArgConstructor;
this.firePropertyChanged(NO_ARG_CONSTRUCTOR_PROPERTY, old, astHasNoArgConstructor);
}
private boolean buildHasNoArgConstructor(ITypeBinding binding) {
return (binding == null) ? false : typeHasNoArgConstructor(binding);
}
protected static boolean typeHasNoArgConstructor(ITypeBinding binding) {
return findNoArgConstructor(binding) != null;
}
protected static IMethodBinding findNoArgConstructor(ITypeBinding binding) {
for (IMethodBinding method : binding.getDeclaredMethods()) {
if (method.isConstructor()) {
if (method.getParameterTypes().length == 0) {
return method;
}
}
}
return null;
}
// ***** private no-arg constructor
public boolean hasPrivateNoArgConstructor() {
return this.hasPrivateNoArgConstructor;
}
private void syncHasPrivateNoArgConstructor(boolean astHasPrivateNoArgConstructor) {
boolean old = this.hasPrivateNoArgConstructor;
this.hasPrivateNoArgConstructor = astHasPrivateNoArgConstructor;
this.firePropertyChanged(PRIVATE_NO_ARG_CONSTRUCTOR_PROPERTY, old, astHasPrivateNoArgConstructor);
}
private boolean buildHasPrivateNoArgConstructor(ITypeBinding binding) {
return (binding == null) ? false : typeHasPrivateNoArgConstructor(binding);
}
protected static boolean typeHasPrivateNoArgConstructor(ITypeBinding binding) {
IMethodBinding method = findNoArgConstructor(binding);
return (method != null) && Modifier.isPrivate(method.getModifiers());
}
// ********** misc **********
public boolean isMapped() {
for (Annotation annotation : this.getAnnotations()) {
if (this.annotationIsMappingAnnotation(annotation)) {
return true;
}
}
return false;
}
private boolean annotationIsMappingAnnotation(Annotation annotation) {
return CollectionTools.contains(this.mappingAnnotationNames(), annotation.getAnnotationName());
}
private Iterator<String> mappingAnnotationNames() {
return this.getAnnotationProvider().typeMappingAnnotationNames();
}
/**
* check only persistable attributes
*/
public boolean hasAnyAnnotatedAttributes() {
for (Iterator<JavaResourcePersistentAttribute> stream = this.persistableAttributes(); stream.hasNext(); ) {
if (stream.next().isAnnotated()) {
return true;
}
}
return false;
}
// ********** types **********
public Iterator<JavaResourcePersistentType> types() {
return this.getTypes().iterator();
}
private Iterable<JavaResourcePersistentType> getTypes() {
return new LiveCloneIterable<JavaResourcePersistentType>(this.types); // read-only
}
public Iterator<JavaResourcePersistentType> allTypes() {
return new TreeIterator<JavaResourcePersistentType>(this) {
@Override
protected Iterator<? extends JavaResourcePersistentType> children(JavaResourcePersistentType type) {
return type.types();
}
};
}
public Iterator<JavaResourcePersistentType> persistableTypes() {
return this.persistableMembers(this.types());
}
private JavaResourcePersistentType getType(String typeName, int occurrence) {
for (JavaResourcePersistentType type : this.getTypes()) {
if (type.isFor(typeName, occurrence)) {
return type;
}
}
return null;
}
private void addType(JavaResourcePersistentType type) {
this.addItemToCollection(type, this.types, TYPES_COLLECTION);
}
private void removeTypes(Collection<JavaResourcePersistentType> remove) {
this.removeItemsFromCollection(remove, this.types, TYPES_COLLECTION);
}
private void initializeTypes(CompilationUnit astRoot) {
TypeDeclaration[] typeDeclarations = this.annotatedElement.getTypes(astRoot);
CounterMap counters = new CounterMap(typeDeclarations.length);
for (TypeDeclaration td : typeDeclarations) {
String tdName = td.getName().getFullyQualifiedName();
int occurrence = counters.increment(tdName);
this.types.add(this.buildType(td, occurrence, astRoot));
}
}
private void syncTypes(CompilationUnit astRoot) {
TypeDeclaration[] typeDeclarations = this.annotatedElement.getTypes(astRoot);
CounterMap counters = new CounterMap(typeDeclarations.length);
HashSet<JavaResourcePersistentType> typesToRemove = new HashSet<JavaResourcePersistentType>(this.types);
for (TypeDeclaration typeDeclaration : typeDeclarations) {
String tdName = typeDeclaration.getName().getFullyQualifiedName();
int occurrence = counters.increment(tdName);
JavaResourcePersistentType type = this.getType(tdName, occurrence);
if (type == null) {
this.addType(this.buildType(typeDeclaration, occurrence, astRoot));
} else {
typesToRemove.remove(type);
type.synchronizeWith(astRoot);
}
}
this.removeTypes(typesToRemove);
}
private JavaResourcePersistentType buildType(TypeDeclaration nestedTypeDeclaration, int occurrence, CompilationUnit astRoot) {
return newInstance(this.getJavaResourceCompilationUnit(), this.annotatedElement, nestedTypeDeclaration, occurrence, astRoot);
}
// ********** fields **********
public Iterator<JavaResourcePersistentAttribute> fields() {
return this.getFields().iterator();
}
private Iterable<JavaResourcePersistentAttribute> getFields() {
return new LiveCloneIterable<JavaResourcePersistentAttribute>(this.fields);
}
public Iterator<JavaResourcePersistentAttribute> persistableFields() {
return this.persistableMembers(this.fields());
}
public Iterator<JavaResourcePersistentAttribute> persistableFieldsWithSpecifiedFieldAccess() {
return new FilteringIterator<JavaResourcePersistentAttribute>(
this.persistableFields(),
FIELD_ACCESS_TYPE_FILTER
);
}
private void addField(JavaResourcePersistentAttribute field) {
this.addItemToCollection(field, this.fields, FIELDS_COLLECTION);
}
private JavaResourcePersistentAttribute getField(String fieldName, int occurrence) {
for (JavaResourcePersistentAttribute field : this.getFields()) {
if (field.isFor(fieldName, occurrence)) {
return field;
}
}
return null;
}
private void removeFields(Collection<JavaResourcePersistentAttribute> remove) {
this.removeItemsFromCollection(remove, this.fields, FIELDS_COLLECTION);
}
private void initializeFields(CompilationUnit astRoot) {
FieldDeclaration[] fieldDeclarations = this.annotatedElement.getFields(astRoot);
CounterMap counters = new CounterMap(fieldDeclarations.length);
for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) {
String fieldName = fragment.getName().getFullyQualifiedName();
int occurrence = counters.increment(fieldName);
this.fields.add(this.buildField(fieldName, occurrence, astRoot));
}
}
}
private void syncFields(CompilationUnit astRoot) {
FieldDeclaration[] fieldDeclarations = this.annotatedElement.getFields(astRoot);
CounterMap counters = new CounterMap(fieldDeclarations.length);
HashSet<JavaResourcePersistentAttribute> fieldsToRemove = new HashSet<JavaResourcePersistentAttribute>(this.fields);
for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) {
String fieldName = fragment.getName().getFullyQualifiedName();
int occurrence = counters.increment(fieldName);
JavaResourcePersistentAttribute field = this.getField(fieldName, occurrence);
if (field == null) {
this.addField(this.buildField(fieldName, occurrence, astRoot));
} else {
fieldsToRemove.remove(field);
field.synchronizeWith(astRoot);
}
}
}
this.removeFields(fieldsToRemove);
}
private JavaResourcePersistentAttribute buildField(String fieldName, int occurrence, CompilationUnit astRoot) {
return SourcePersistentAttribute.newInstance(this, this.annotatedElement, fieldName, occurrence, this.getJavaResourceCompilationUnit(), astRoot);
}
// minimize scope of suppressed warnings
@SuppressWarnings("unchecked")
private static List<VariableDeclarationFragment> fragments(FieldDeclaration fd) {
return fd.fragments();
}
// ********** methods **********
public Iterator<JavaResourcePersistentAttribute> methods() {
return this.getMethods().iterator();
}
private Iterable<JavaResourcePersistentAttribute> getMethods() {
return new LiveCloneIterable<JavaResourcePersistentAttribute>(this.methods);
}
public Iterator<JavaResourcePersistentAttribute> persistableProperties() {
return this.persistableMembers(this.methods());
}
public Iterator<JavaResourcePersistentAttribute> persistablePropertiesWithSpecifiedPropertyAccess() {
return new FilteringIterator<JavaResourcePersistentAttribute>(
this.persistableProperties(),
PROPERTY_ACCESS_TYPE_FILTER
);
}
private JavaResourcePersistentAttribute getMethod(MethodSignature signature, int occurrence) {
for (JavaResourcePersistentAttribute method : this.getMethods()) {
if (method.isFor(signature, occurrence)) {
return method;
}
}
return null;
}
private void addMethod(JavaResourcePersistentAttribute method) {
this.addItemToCollection(method, this.methods, METHODS_COLLECTION);
}
private void removeMethods(Collection<JavaResourcePersistentAttribute> remove) {
this.removeItemsFromCollection(remove, this.methods, METHODS_COLLECTION);
}
private void initializeMethods(CompilationUnit astRoot) {
MethodDeclaration[] methodDeclarations = this.annotatedElement.getMethods(astRoot);
CounterMap counters = new CounterMap(methodDeclarations.length);
for (MethodDeclaration methodDeclaration : methodDeclarations) {
MethodSignature signature = ASTTools.buildMethodSignature(methodDeclaration);
int occurrence = counters.increment(signature);
this.methods.add(this.buildMethod(signature, occurrence, astRoot));
}
}
private void syncMethods(CompilationUnit astRoot) {
MethodDeclaration[] methodDeclarations = this.annotatedElement.getMethods(astRoot);
CounterMap counters = new CounterMap(methodDeclarations.length);
HashSet<JavaResourcePersistentAttribute> methodsToRemove = new HashSet<JavaResourcePersistentAttribute>(this.methods);
for (MethodDeclaration methodDeclaration : methodDeclarations) {
MethodSignature signature = ASTTools.buildMethodSignature(methodDeclaration);
int occurrence = counters.increment(signature);
JavaResourcePersistentAttribute method = this.getMethod(signature, occurrence);
if (method == null) {
this.addMethod(this.buildMethod(signature, occurrence, astRoot));
} else {
methodsToRemove.remove(method);
method.synchronizeWith(astRoot);
}
}
this.removeMethods(methodsToRemove);
}
private JavaResourcePersistentAttribute buildMethod(MethodSignature signature, int occurrence, CompilationUnit astRoot) {
return SourcePersistentAttribute.newInstance(this, this.annotatedElement, signature, occurrence, this.getJavaResourceCompilationUnit(), astRoot);
}
// ********** attributes **********
@SuppressWarnings("unchecked")
public Iterator<JavaResourcePersistentAttribute> persistableAttributes() {
return new CompositeIterator<JavaResourcePersistentAttribute>(
this.persistableFields(),
this.persistableProperties()
);
}
public Iterator<JavaResourcePersistentAttribute> persistableAttributes(AccessType specifiedAccess) {
switch (specifiedAccess) {
case FIELD :
return this.persistableAttributesForFieldAccessType();
case PROPERTY :
return this.persistableAttributesForPropertyAccessType();
default :
throw new IllegalArgumentException("unknown access: " + specifiedAccess); //$NON-NLS-1$
}
}
@SuppressWarnings("unchecked")
private Iterator<JavaResourcePersistentAttribute> persistableAttributesForFieldAccessType() {
return new CompositeIterator<JavaResourcePersistentAttribute>(
this.persistableFields(),
this.persistablePropertiesWithSpecifiedPropertyAccess()
);
}
@SuppressWarnings("unchecked")
private Iterator<JavaResourcePersistentAttribute> persistableAttributesForPropertyAccessType() {
return new CompositeIterator<JavaResourcePersistentAttribute>(
this.persistableProperties(),
this.persistableFieldsWithSpecifiedFieldAccess()
);
}
// ********** metamodel **********
// ***** StaticMetamodel
private void setStaticMetamodelAnnotation(StaticMetamodelAnnotation staticMetamodelAnnotation) {
StaticMetamodelAnnotation old = this.staticMetamodelAnnotation;
this.staticMetamodelAnnotation = staticMetamodelAnnotation;
this.firePropertyChanged(STATIC_METAMODEL_ANNOTATION_PROPERTY, old, this.staticMetamodelAnnotation);
}
private void addInitialStaticMetamodelAnnotation(CompilationUnit astRoot) {
if (this.staticMetamodelAnnotation == null) { // ignore duplicates
this.staticMetamodelAnnotation = this.buildStaticMetamodelAnnotation(astRoot);
}
}
private StaticMetamodelAnnotation buildStaticMetamodelAnnotation(CompilationUnit astRoot) {
StaticMetamodelAnnotation annotation = STATIC_METAMODEL_ANNOTATION_DEFINITION.buildAnnotation(this, this.annotatedElement);
annotation.initialize(astRoot);
return annotation;
}
private void syncStaticMetamodelAnnotation(CompilationUnit astRoot, ITypeBinding binding) {
if (this.bindingContainsStaticMetamodelAnnotation(binding)) {
if (this.staticMetamodelAnnotation != null) {
this.staticMetamodelAnnotation.synchronizeWith(astRoot);
} else {
this.setStaticMetamodelAnnotation(this.buildStaticMetamodelAnnotation(astRoot));
}
} else {
this.setStaticMetamodelAnnotation(null);
}
}
private boolean bindingContainsStaticMetamodelAnnotation(ITypeBinding binding) {
return this.bindingContainsAnnotation(binding, STATIC_METAMODEL_ANNOTATION_DEFINITION.getAnnotationName());
}
// ***** Generated
public GeneratedAnnotation getGeneratedAnnotation() {
return this.generatedAnnotation;
}
private void setGeneratedAnnotation(GeneratedAnnotation generatedAnnotation) {
GeneratedAnnotation old = this.generatedAnnotation;
this.generatedAnnotation = generatedAnnotation;
this.firePropertyChanged(GENERATED_ANNOTATION_PROPERTY, old, this.generatedAnnotation);
}
private void addInitialGeneratedAnnotation(CompilationUnit astRoot) {
if (this.generatedAnnotation == null) { // ignore duplicates
this.generatedAnnotation = this.buildGeneratedAnnotation(astRoot);
}
}
private GeneratedAnnotation buildGeneratedAnnotation(CompilationUnit astRoot) {
GeneratedAnnotation annotation = GENERATED_ANNOTATION_DEFINITION.buildAnnotation(this, this.annotatedElement);
annotation.initialize(astRoot);
return annotation;
}
private void syncGeneratedAnnotation(CompilationUnit astRoot, ITypeBinding binding) {
if (this.bindingContainsGeneratedAnnotation(binding)) {
if (this.generatedAnnotation != null) {
this.generatedAnnotation.synchronizeWith(astRoot);
} else {
this.setGeneratedAnnotation(this.buildGeneratedAnnotation(astRoot));
}
} else {
this.setGeneratedAnnotation(null);
}
}
private boolean bindingContainsGeneratedAnnotation(ITypeBinding binding) {
return this.bindingContainsAnnotation(binding, GENERATED_ANNOTATION_DEFINITION.getAnnotationName());
}
private boolean bindingContainsAnnotation(ITypeBinding binding, String annotationName) {
for (IAnnotationBinding annotationBinding : binding.getAnnotations()) {
ITypeBinding annotationTypeBinding = annotationBinding.getAnnotationType();
if ((annotationTypeBinding != null) && annotationTypeBinding.getQualifiedName().equals(annotationName)) {
return true;
}
}
return false;
}
/**
* The type must be:<ul>
* <li>in the specified source folder
* <li>a top-level type
* <li>annotated with <code>&#64;javax.annotation.Generated</code> with
* the appropriate <code>value</code> and <code>date</code>
* <li>either itself or one of its nested types annotated with
* <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
* </ul>
*/
public boolean isGeneratedMetamodelTopLevelType(IPackageFragmentRoot sourceFolder) {
if ( ! this.getSourceFolder().equals(sourceFolder)) {
return false;
}
return this.isGeneratedMetamodelTopLevelType();
}
/**
* The type must be:<ul>
* <li>a top-level type
* <li>annotated with <code>&#64;javax.annotation.Generated</code> with
* the appropriate <code>value</code> and <code>date</code>
* <li>either itself or one of its nested types annotated with
* <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
* </ul>
*/
public boolean isGeneratedMetamodelTopLevelType() {
if ( ! this.isGenerated()) {
return false;
}
// if we get here we know we have a top-level type, since only top-level
// types are annotated @Generated; now see if anything is a metamodel
for (Iterator<JavaResourcePersistentType> stream = this.allTypes(); stream.hasNext(); ) {
JavaResourcePersistentType2_0 type = (JavaResourcePersistentType2_0) stream.next();
if (type.isMetamodel()) {
return true;
}
}
return false;
}
/**
* The type must be annotated with
* <code>&#64;javax.annotation.Generated</code> with the appropriate
* <code>value</code> and <code>date</code>.
*/
private boolean isGenerated() {
if (this.generatedAnnotation == null) {
return false;
}
if (this.generatedAnnotation.valuesSize() != 1) {
return false;
}
if ( ! this.generatedAnnotation.getValue(0).equals(METAMODEL_GENERATED_ANNOTATION_VALUE)) {
return false;
}
if (StringTools.stringIsEmpty(this.generatedAnnotation.getDate())) {
return false;
}
return true;
}
/**
* The type must be annotated with
* <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>.
*/
public boolean isMetamodel() {
return this.staticMetamodelAnnotation != null;
}
private IPackageFragmentRoot getSourceFolder() {
return (IPackageFragmentRoot) this.getJavaResourceCompilationUnit().getCompilationUnit().getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
}
// ********** CounterMap **********
private static class CounterMap {
private final HashMap<Object, SimpleIntReference> counters;
protected CounterMap(int initialCapacity) {
super();
this.counters = new HashMap<Object, SimpleIntReference>(initialCapacity);
}
/**
* Return the incremented count for the specified object.
*/
int increment(Object o) {
SimpleIntReference counter = this.counters.get(o);
if (counter == null) {
counter = new SimpleIntReference();
this.counters.put(o, counter);
}
counter.increment();
return counter.getValue();
}
}
}