| /******************************************************************************* |
| * Copyright (c) 2007, 2008 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.core.internal.resource.java; |
| |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.ListIterator; |
| import java.util.Vector; |
| |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| 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.core.internal.utility.jdt.JDTTools; |
| import org.eclipse.jpt.core.internal.utility.jdt.JDTType; |
| import org.eclipse.jpt.core.resource.java.AccessType; |
| import org.eclipse.jpt.core.resource.java.Annotation; |
| import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; |
| import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; |
| import org.eclipse.jpt.core.resource.java.JpaCompilationUnit; |
| import org.eclipse.jpt.core.resource.java.NestableAnnotation; |
| import org.eclipse.jpt.core.utility.jdt.Type; |
| import org.eclipse.jpt.utility.MethodSignature; |
| import org.eclipse.jpt.utility.internal.CollectionTools; |
| import org.eclipse.jpt.utility.internal.Counter; |
| import org.eclipse.jpt.utility.internal.iterators.CloneIterator; |
| import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; |
| import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; |
| |
| public class JavaResourcePersistentTypeImpl |
| extends AbstractJavaResourcePersistentMember<Type> |
| implements JavaResourcePersistentType |
| { |
| private String qualifiedName; |
| |
| private String name; |
| |
| private String superClassQualifiedName; |
| |
| private boolean abstract_; // 'abstract' is a reserved word |
| |
| /** |
| * store all member types including those that aren't persistable so we can |
| * generate validation errors |
| */ |
| private final Vector<JavaResourcePersistentType> nestedTypes; |
| |
| private final Vector<JavaResourcePersistentAttribute> fields; |
| |
| private final Vector<JavaResourcePersistentAttribute> methods; |
| |
| private AccessType accessType; |
| |
| |
| // ********** construction ********** |
| |
| /** |
| * build top-level persistent type |
| */ |
| // TODO use JPA factory |
| public static JavaResourcePersistentType newInstance( |
| JpaCompilationUnit jpaCompilationUnit, |
| TypeDeclaration typeDeclaration, |
| CompilationUnit astRoot) { |
| Type type = new JDTType( |
| typeDeclaration, |
| jpaCompilationUnit.getCompilationUnit(), |
| jpaCompilationUnit.getModifySharedDocumentCommandExecutorProvider(), |
| jpaCompilationUnit.getAnnotationEditFormatter()); |
| JavaResourcePersistentType jrpt = new JavaResourcePersistentTypeImpl(jpaCompilationUnit, type); |
| jrpt.initialize(astRoot); |
| return jrpt; |
| } |
| |
| /** |
| * build nested persistent type |
| */ |
| // TODO use JPA factory |
| protected static JavaResourcePersistentType newInstance( |
| JpaCompilationUnit jpaCompilationUnit, |
| Type declaringType, |
| TypeDeclaration typeDeclaration, |
| int occurrence, |
| CompilationUnit astRoot) { |
| Type type = new JDTType( |
| declaringType, |
| typeDeclaration, |
| occurrence, |
| jpaCompilationUnit.getCompilationUnit(), |
| jpaCompilationUnit.getModifySharedDocumentCommandExecutorProvider(), |
| jpaCompilationUnit.getAnnotationEditFormatter()); |
| JavaResourcePersistentType jrpt = new JavaResourcePersistentTypeImpl(jpaCompilationUnit, type); |
| jrpt.initialize(astRoot); |
| return jrpt; |
| } |
| |
| public JavaResourcePersistentTypeImpl(JpaCompilationUnit jpaCompilationUnit, Type type) { |
| super(jpaCompilationUnit, type); |
| this.nestedTypes = new Vector<JavaResourcePersistentType>(); |
| this.fields = new Vector<JavaResourcePersistentAttribute>(); |
| this.methods = new Vector<JavaResourcePersistentAttribute>(); |
| } |
| |
| @Override |
| public void initialize(CompilationUnit astRoot) { |
| super.initialize(astRoot); |
| this.qualifiedName = this.buildQualifiedName(astRoot); |
| this.name = this.buildName(astRoot); |
| this.superClassQualifiedName = this.buildSuperClassQualifiedName(astRoot); |
| this.abstract_ = this.buildAbstract(astRoot); |
| this.initializeNestedTypes(astRoot); |
| this.initializeFields(astRoot); |
| this.initializeMethods(astRoot); |
| this.accessType = this.buildAccessType(); |
| } |
| |
| protected void initializeNestedTypes(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| for (TypeDeclaration td : this.getMember().getTypes(astRoot)) { |
| String tdName = td.getName().getFullyQualifiedName(); |
| int occurrence = counters.increment(tdName); |
| this.nestedTypes.add(this.buildNestedType(td, occurrence, astRoot)); |
| } |
| } |
| |
| protected void initializeFields(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| for (FieldDeclaration fieldDeclaration : this.getMember().getFields(astRoot)) { |
| for (VariableDeclarationFragment fragment : fragments(fieldDeclaration)) { |
| String fieldName = fragment.getName().getFullyQualifiedName(); |
| int occurrence = counters.increment(fieldName); |
| this.fields.add(this.buildField(fieldName, occurrence, astRoot)); |
| } |
| } |
| } |
| |
| protected void initializeMethods(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| for (MethodDeclaration methodDeclaration : this.getMember().getMethods(astRoot)) { |
| MethodSignature signature = JDTTools.buildMethodSignature(methodDeclaration); |
| int occurrence = counters.increment(signature); |
| this.methods.add(this.buildMethod(signature, occurrence, astRoot)); |
| } |
| } |
| |
| |
| // ********** AbstractJavaResourcePersistentMember implementation ********** |
| |
| @Override |
| protected Annotation buildMappingAnnotation(String mappingAnnotationName) { |
| return getAnnotationProvider().buildTypeMappingAnnotation(this, getMember(), mappingAnnotationName); |
| } |
| |
| @Override |
| protected Annotation buildNullMappingAnnotation(String annotationName) { |
| return getAnnotationProvider().buildNullTypeMappingAnnotation(this, getMember(), annotationName); |
| } |
| |
| @Override |
| protected Annotation buildAnnotation(String annotationName) { |
| return getAnnotationProvider().buildTypeAnnotation(this, getMember(), annotationName); |
| } |
| |
| @Override |
| protected Annotation buildNullAnnotation(String annotationName) { |
| return getAnnotationProvider().buildNullTypeAnnotation(this, getMember(), annotationName); |
| } |
| |
| @Override |
| protected ListIterator<String> possibleMappingAnnotationNames() { |
| return getAnnotationProvider().typeMappingAnnotationNames(); |
| } |
| |
| @Override |
| protected boolean isPossibleAnnotation(String annotationName) { |
| return CollectionTools.contains(getAnnotationProvider().typeAnnotationNames(), annotationName); |
| } |
| |
| @Override |
| protected boolean isPossibleMappingAnnotation(String annotationName) { |
| return CollectionTools.contains(getAnnotationProvider().typeMappingAnnotationNames(), annotationName); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| //overriding purely to suppress the warning you get at the class level |
| public ListIterator<NestableAnnotation> annotations(String nestableAnnotationName, String containerAnnotationName) { |
| return super.annotations(nestableAnnotationName, containerAnnotationName); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| //overriding purely to suppress the warning you get at the class level |
| public Iterator<Annotation> mappingAnnotations() { |
| return super.mappingAnnotations(); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| //overriding purely to suppress the warning you get at the class level |
| public Iterator<Annotation> annotations() { |
| return super.annotations(); |
| } |
| |
| @Override |
| public void resolveTypes(CompilationUnit astRoot) { |
| super.resolveTypes(astRoot); |
| |
| this.setSuperClassQualifiedName(this.buildSuperClassQualifiedName(astRoot)); |
| |
| for (Iterator<JavaResourcePersistentAttribute> stream = this.fields_(); stream.hasNext(); ) { |
| stream.next().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.updateMethods(astRoot); |
| |
| for (Iterator<JavaResourcePersistentAttribute> stream = this.methods_(); stream.hasNext(); ) { |
| stream.next().resolveTypes(astRoot); |
| } |
| for (Iterator<JavaResourcePersistentType> stream = this.nestedTypes_(); stream.hasNext(); ) { |
| stream.next().resolveTypes(astRoot); |
| } |
| } |
| |
| @Override |
| public void toString(StringBuilder sb) { |
| sb.append(this.name); |
| } |
| |
| |
| // ******** JavaResourcePersistentType implementation ******** |
| |
| public JavaResourcePersistentType getJavaPersistentTypeResource(String fullyQualifiedTypeName) { |
| // TODO not sure why a null name is coming through here... ~bjv |
| // if (fullyQualifiedTypeName.equals(this.getQualifiedName())) { |
| if (this.getQualifiedName().equals(fullyQualifiedTypeName)) { |
| return this; |
| } |
| for (Iterator<JavaResourcePersistentType> stream = this.nestedTypes(); stream.hasNext(); ) { |
| JavaResourcePersistentType jrpt = stream.next(); |
| // recurse |
| JavaResourcePersistentType nestedJRPT = jrpt.getJavaPersistentTypeResource(fullyQualifiedTypeName); |
| if (nestedJRPT != null) { |
| return nestedJRPT; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * check only persistable attributes |
| */ |
| public boolean hasAnyAttributeAnnotations() { |
| for (Iterator<JavaResourcePersistentAttribute> stream = this.attributes(); stream.hasNext(); ) { |
| if (stream.next().hasAnyAnnotation()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| // ********** nested types ********** |
| |
| /** |
| * return only persistable nested types |
| */ |
| public Iterator<JavaResourcePersistentType> nestedTypes() { |
| //TODO since we are filtering how do we handle the case where a type becomes persistable? |
| //what kind of change notificiation for that case? |
| return new FilteringIterator<JavaResourcePersistentType, JavaResourcePersistentType>(this.nestedTypes_()) { |
| @Override |
| protected boolean accept(JavaResourcePersistentType jrpt) { |
| return jrpt.isPersistable(); |
| } |
| }; |
| } |
| |
| /** |
| * *all* nested types |
| */ |
| protected Iterator<JavaResourcePersistentType> nestedTypes_() { |
| return new CloneIterator<JavaResourcePersistentType>(this.nestedTypes); |
| } |
| |
| protected void addNestedType(JavaResourcePersistentType nestedType) { |
| this.addItemToCollection(nestedType, this.nestedTypes, NESTED_TYPES_COLLECTION); |
| } |
| |
| protected void removeNestedType(JavaResourcePersistentType nestedType) { |
| this.removeItemFromCollection(nestedType, this.nestedTypes, NESTED_TYPES_COLLECTION); |
| } |
| |
| protected void removeNestedTypes(Collection<JavaResourcePersistentType> remove) { |
| this.removeItemsFromCollection(remove, this.nestedTypes, NESTED_TYPES_COLLECTION); |
| } |
| |
| protected JavaResourcePersistentType getNestedType(String typeName, int occurrence) { |
| for (Iterator<JavaResourcePersistentType> stream = this.nestedTypes_(); stream.hasNext(); ) { |
| JavaResourcePersistentType nestedType = stream.next(); |
| if (nestedType.isFor(typeName, occurrence)) { |
| return nestedType; |
| } |
| } |
| return null; |
| } |
| |
| |
| // ********** attributes ********** |
| |
| /** |
| * return only persistable attributes |
| */ |
| // TODO since we are filtering, how do we handle the case where an attribute becomes persistable? |
| // what kind of change notification for that case? |
| public Iterator<JavaResourcePersistentAttribute> attributes() { |
| return persistableMembers(this.attributes_()); |
| } |
| |
| /** |
| * *all* fields and methods |
| */ |
| @SuppressWarnings("unchecked") |
| protected Iterator<JavaResourcePersistentAttribute> attributes_() { |
| return new CompositeIterator<JavaResourcePersistentAttribute>(this.fields_(), this.methods_()); |
| } |
| |
| |
| // ********** fields ********** |
| |
| /** |
| * return only persistable fields |
| */ |
| public Iterator<JavaResourcePersistentAttribute> fields() { |
| return persistableMembers(this.fields_()); |
| } |
| |
| /** |
| * *all* fields |
| */ |
| protected Iterator<JavaResourcePersistentAttribute> fields_() { |
| return new CloneIterator<JavaResourcePersistentAttribute>(this.fields); |
| } |
| |
| protected void addField(JavaResourcePersistentAttribute attribute) { |
| this.addItemToCollection(attribute, this.fields, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected void removeField(JavaResourcePersistentAttribute attribute) { |
| this.removeItemFromCollection(attribute, this.fields, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected void removeFields(Collection<JavaResourcePersistentAttribute> remove) { |
| this.removeItemsFromCollection(remove, this.fields, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected JavaResourcePersistentAttribute getField(String fieldName, int occurrence) { |
| for (Iterator<JavaResourcePersistentAttribute> stream = this.fields_(); stream.hasNext(); ) { |
| JavaResourcePersistentAttribute field = stream.next(); |
| if (field.isFor(fieldName, occurrence)) { |
| return field; |
| } |
| } |
| return null; |
| } |
| |
| |
| // ********** methods ********** |
| |
| /** |
| * return only persistable properties |
| */ |
| public Iterator<JavaResourcePersistentAttribute> properties() { |
| return persistableMembers(this.methods_()); |
| } |
| |
| /** |
| * *all* methods |
| */ |
| protected Iterator<JavaResourcePersistentAttribute> methods_() { |
| return new CloneIterator<JavaResourcePersistentAttribute>(this.methods); |
| } |
| |
| protected void addMethod(JavaResourcePersistentAttribute attribute) { |
| this.addItemToCollection(attribute, this.methods, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected void removeMethod(JavaResourcePersistentAttribute attribute) { |
| this.removeItemFromCollection(attribute, this.methods, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected void removeMethods(Collection<JavaResourcePersistentAttribute> remove) { |
| this.removeItemsFromCollection(remove, this.methods, ATTRIBUTES_COLLECTION); |
| } |
| |
| protected JavaResourcePersistentAttribute getMethod(MethodSignature signature, int occurrence) { |
| for (Iterator<JavaResourcePersistentAttribute> stream = this.methods_(); stream.hasNext(); ) { |
| JavaResourcePersistentAttribute method = stream.next(); |
| if (method.isFor(signature, occurrence)) { |
| return method; |
| } |
| } |
| return null; |
| } |
| |
| |
| // ********** simple instance variables ********** |
| |
| public String getQualifiedName() { |
| return this.qualifiedName; |
| } |
| |
| protected void setQualifiedName(String qualifiedName) { |
| String old = this.qualifiedName; |
| this.qualifiedName = qualifiedName; |
| this.firePropertyChanged(QUALIFIED_NAME_PROPERTY, old, qualifiedName); |
| } |
| |
| public String getName() { |
| return this.name; |
| } |
| |
| protected void setName(String name) { |
| String old = this.name; |
| this.name = name; |
| this.firePropertyChanged(NAME_PROPERTY, old, name); |
| } |
| |
| public String getSuperClassQualifiedName() { |
| return this.superClassQualifiedName; |
| } |
| |
| protected void setSuperClassQualifiedName(String superClassQualifiedName) { |
| String old = this.superClassQualifiedName; |
| this.superClassQualifiedName = superClassQualifiedName; |
| this.firePropertyChanged(SUPER_CLASS_QUALIFIED_NAME_PROPERTY, old, superClassQualifiedName); |
| } |
| |
| public boolean isAbstract() { |
| return this.abstract_; |
| } |
| |
| protected void setAbstract(boolean abstract_) { |
| boolean old = this.abstract_; |
| this.abstract_ = abstract_; |
| this.firePropertyChanged(ABSTRACT_PROPERTY, old, abstract_); |
| } |
| |
| public AccessType getAccess() { |
| return this.accessType; |
| } |
| |
| // TODO |
| //seems we could have a public changeAccess() api which would |
| //move all annotations from fields to their corresponding methods or vice versa |
| //though of course it's more complicated than that since what if the |
| //corresponding field/method does not exist? |
| //making this internal since it should only be set based on changes in the source, the |
| //context model should not need to set this |
| protected void setAccess(AccessType accessType) { |
| AccessType old = this.accessType; |
| this.accessType = accessType; |
| this.firePropertyChanged(ACCESS_PROPERTY, old, accessType); |
| } |
| |
| |
| // ********** update from Java ********** |
| |
| @Override |
| public void updateFromJava(CompilationUnit astRoot) { |
| super.updateFromJava(astRoot); |
| this.setQualifiedName(this.buildQualifiedName(astRoot)); |
| this.setName(this.buildName(astRoot)); |
| this.setSuperClassQualifiedName(this.buildSuperClassQualifiedName(astRoot)); |
| this.setAbstract(this.buildAbstract(astRoot)); |
| this.updateNestedTypes(astRoot); |
| this.updateFields(astRoot); |
| this.updateMethods(astRoot); |
| this.setAccess(this.buildAccessType()); |
| } |
| |
| protected void updateNestedTypes(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| @SuppressWarnings("unchecked") |
| Vector<JavaResourcePersistentType> nestedTypesToRemove = (Vector<JavaResourcePersistentType>) this.nestedTypes.clone(); |
| for (TypeDeclaration typeDeclaration : this.getMember().getTypes(astRoot)) { |
| String tdName = typeDeclaration.getName().getFullyQualifiedName(); |
| int occurrence = counters.increment(tdName); |
| |
| JavaResourcePersistentType nestedType = this.getNestedType(tdName, occurrence); |
| if (nestedType == null) { |
| this.addNestedType(this.buildNestedType(typeDeclaration, occurrence, astRoot)); |
| } else { |
| nestedTypesToRemove.remove(nestedType); |
| nestedType.updateFromJava(astRoot); |
| } |
| } |
| this.removeNestedTypes(nestedTypesToRemove); |
| } |
| |
| protected void updateFields(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| @SuppressWarnings("unchecked") |
| Vector<JavaResourcePersistentAttribute> fieldsToRemove = (Vector<JavaResourcePersistentAttribute>) this.fields.clone(); |
| for (FieldDeclaration fieldDeclaration : this.getMember().getFields(astRoot)) { |
| 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.updateFromJava(astRoot); |
| } |
| } |
| } |
| this.removeFields(fieldsToRemove); |
| } |
| |
| protected void updateMethods(CompilationUnit astRoot) { |
| CounterMap counters = new CounterMap(); |
| @SuppressWarnings("unchecked") |
| Vector<JavaResourcePersistentAttribute> methodsToRemove = (Vector<JavaResourcePersistentAttribute>) this.methods.clone(); |
| for (MethodDeclaration methodDeclaration : this.getMember().getMethods(astRoot)) { |
| MethodSignature signature = JDTTools.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.updateFromJava(astRoot); |
| } |
| } |
| this.removeMethods(methodsToRemove); |
| } |
| |
| |
| // ********** building state from AST ********** |
| |
| protected String buildQualifiedName(CompilationUnit astRoot) { |
| return this.getMember().getBinding(astRoot).getQualifiedName(); |
| } |
| |
| protected String buildName(CompilationUnit astRoot) { |
| return this.getMember().getBinding(astRoot).getName(); |
| } |
| |
| protected String buildSuperClassQualifiedName(CompilationUnit astRoot) { |
| ITypeBinding typeBinding = this.getMember().getBinding(astRoot); |
| if (typeBinding == null) { |
| return null; |
| } |
| ITypeBinding superClassTypeBinding = typeBinding.getSuperclass(); |
| if (superClassTypeBinding == null) { |
| return null; |
| } |
| return superClassTypeBinding.getTypeDeclaration().getQualifiedName(); |
| } |
| |
| protected boolean buildAbstract(CompilationUnit astRoot) { |
| return Modifier.isAbstract(this.getMember().getBinding(astRoot).getModifiers()); |
| } |
| |
| // TODO use JPA factory |
| protected JavaResourcePersistentType buildNestedType(TypeDeclaration nestedTypeDeclaration, int occurrence, CompilationUnit astRoot) { |
| return newInstance(this.getJpaCompilationUnit(), this.getMember(), nestedTypeDeclaration, occurrence, astRoot); |
| } |
| |
| // TODO use JPA factory |
| protected JavaResourcePersistentAttribute buildField(String fieldName, int occurrence, CompilationUnit astRoot) { |
| return JavaResourcePersistentAttributeImpl.newInstance(this, this.getMember(), fieldName, occurrence, this.getJpaCompilationUnit(), astRoot); |
| } |
| |
| // TODO use JPA factory |
| protected JavaResourcePersistentAttribute buildMethod(MethodSignature signature, int occurrence, CompilationUnit astRoot) { |
| return JavaResourcePersistentAttributeImpl.newInstance(this, this.getMember(), signature, occurrence, this.getJpaCompilationUnit(), astRoot); |
| } |
| |
| /** |
| * Return the AccessType currently implied by the Java source code: |
| * - if only Fields are annotated => FIELD |
| * - if only Properties are annotated => PROPERTY |
| * - if both Fields and Properties are annotated => FIELD |
| * - if nothing is annotated |
| * - and fields exist => FIELD |
| * - and properties exist, but no fields exist => PROPERTY |
| * - and neither fields nor properties exist => null at this level (FIELD in the context model) |
| */ |
| protected AccessType buildAccessType() { |
| boolean hasPersistableFields = false; |
| boolean hasPersistableProperties = false; |
| for (JavaResourcePersistentAttribute field : CollectionTools.iterable(fields())) { |
| hasPersistableFields = true; |
| if (field.hasAnyAnnotation()) { |
| // any field is annotated => FIELD |
| return AccessType.FIELD; |
| } |
| } |
| for (JavaResourcePersistentAttribute property : CollectionTools.iterable(properties())) { |
| hasPersistableProperties = true; |
| if (property.hasAnyAnnotation()) { |
| // none of the fields are annotated and a getter is annotated => PROPERTY |
| return AccessType.PROPERTY; |
| } |
| } |
| |
| if (hasPersistableProperties && !hasPersistableFields) { |
| return AccessType.PROPERTY; |
| } |
| //no annotations exist, access is null at the resource model level |
| return null; |
| } |
| |
| |
| // ********** static methods ********** |
| |
| // minimize scope of suppressed warnings |
| @SuppressWarnings("unchecked") |
| protected static List<VariableDeclarationFragment> fragments(FieldDeclaration fd) { |
| return fd.fragments(); |
| } |
| |
| |
| // ********** StringCounter ********** |
| |
| protected static class CounterMap { |
| HashMap<Object, Counter> counters = new HashMap<Object, Counter>(); |
| |
| /** |
| * Return the incremented count for the specified object. |
| */ |
| int increment(Object o) { |
| Counter counter = this.counters.get(o); |
| if (counter == null) { |
| counter = new Counter(); |
| this.counters.put(o, counter); |
| } |
| counter.increment(); |
| return counter.count(); |
| } |
| } |
| |
| } |