diff options
author | bvosburgh | 2009-05-18 21:07:33 +0000 |
---|---|---|
committer | bvosburgh | 2009-05-18 21:07:33 +0000 |
commit | 2671ada902d4f72607ce31d28c51515b1753172b (patch) | |
tree | ef4fb4708ef872df84d7b2a5d663fdb3a739da56 /jpa/plugins/org.eclipse.jpt.core/src/org | |
parent | 1f4904357b6c5aa2311ce345ce46b89a0ef5a26b (diff) | |
download | webtools.dali-2671ada902d4f72607ce31d28c51515b1753172b.tar.gz webtools.dali-2671ada902d4f72607ce31d28c51515b1753172b.tar.xz webtools.dali-2671ada902d4f72607ce31d28c51515b1753172b.zip |
[274692] referencing types on the classpath
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.core/src/org')
36 files changed, 1546 insertions, 796 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java index c5192ac80f..15229384f9 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java @@ -20,8 +20,10 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.ElementChangedEvent; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jpt.core.context.JpaRootContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourceCompilationUnit; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentTypeCache; import org.eclipse.jpt.core.resource.xml.JpaXmlResource; import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.ConnectionProfile; @@ -109,7 +111,35 @@ public interface JpaProject */ JpaFile getJpaFile(IFile file); - + + // ********** external Java resource compilation units ********** + + /** + * ID string used when the JPA project's collection of external Java + * resource compilation units changes. + * @see #addCollectionChangeListener(String, org.eclipse.jpt.utility.model.listener.CollectionChangeListener) + */ + String EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION = "externalJavaResourceCompilationUnits"; //$NON-NLS-1$ + + /** + * Return the JPA project's external Java resource compilation units. + */ + Iterator<JavaResourceCompilationUnit> externalJavaResourceCompilationUnits(); + + /** + * Return the size of the JPA project's external Java resource compilation units. + */ + int externalJavaResourceCompilationUnitsSize(); + + + // ********** external Java resource persistent types ********** + + /** + * Return the JPA project's external Java resource persistent type cache. + */ + JavaResourcePersistentTypeCache getExternalJavaResourcePersistentTypeCache(); + + // ********** xml resources ********** /** @@ -147,7 +177,7 @@ public interface JpaProject /** * Return the Java resource persistent type for the specified type. - * Return null if absent. + * Return null if invalid or absent. */ JavaResourcePersistentType getJavaResourcePersistentType(String typeName); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JarFile.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JarFile.java index 8f3d846107..119dc26876 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JarFile.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/java/JarFile.java @@ -35,6 +35,7 @@ public interface JarFile { /** * Return the JAR file's Java persistent types. + * Return only the types that are annotated with JPA annotations. */ Iterator<JavaPersistentType> javaPersistentTypes(); String JAVA_PERSISTENT_TYPES_COLLECTION = "javaPersistentTypes"; //$NON-NLS-1$ diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java index e235565bf2..d4b28f13bc 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java @@ -10,8 +10,10 @@ package org.eclipse.jpt.core.internal; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.Vector; import org.eclipse.core.resources.IFile; @@ -32,7 +34,9 @@ import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaElementDelta; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jpt.core.JpaDataSource; import org.eclipse.jpt.core.JpaFile; import org.eclipse.jpt.core.JpaPlatform; @@ -41,6 +45,8 @@ import org.eclipse.jpt.core.JpaResourceModel; import org.eclipse.jpt.core.JpaResourceModelListener; import org.eclipse.jpt.core.JptCorePlugin; import org.eclipse.jpt.core.context.JpaRootContextNode; +import org.eclipse.jpt.core.internal.resource.java.binary.BinaryPersistentTypeCache; +import org.eclipse.jpt.core.internal.resource.java.source.SourceCompilationUnit; import org.eclipse.jpt.core.internal.utility.PlatformTools; import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; @@ -48,6 +54,7 @@ import org.eclipse.jpt.core.resource.java.JavaResourceCompilationUnit; import org.eclipse.jpt.core.resource.java.JavaResourceNode; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentTypeCache; import org.eclipse.jpt.core.resource.xml.JpaXmlResource; import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.ConnectionProfile; @@ -59,16 +66,26 @@ import org.eclipse.jpt.utility.internal.BitTools; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.ThreadLocalCommandExecutor; import org.eclipse.jpt.utility.internal.iterables.CloneIterable; -import org.eclipse.jpt.utility.internal.iterators.CloneIterator; -import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; -import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; -import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.TransformationIterable; import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException; import org.eclipse.wst.validation.internal.provisional.core.IMessage; import org.eclipse.wst.validation.internal.provisional.core.IReporter; /** + * JPA project. Holds all the JPA stuff. * + * The JPA platform provides the hooks for vendor-specific stuff. + * + * The JPA files are the "resource" model (i.e. objects that correspond directly + * to Eclipse resources; e.g. Java source code files, XML files, JAR files). + * + * The root context node is the "context"model (i.e. objects that attempt to + * model the JPA spec, using the "resource" model as an adapter to the Eclipse + * resources). + * + * The data source is an adapter to the DTP meta-data model. */ public abstract class AbstractJpaProject extends AbstractJpaNode @@ -91,7 +108,17 @@ public abstract class AbstractJpaProject * orm.xml * java */ - protected final Vector<JpaFile> jpaFiles; + protected final Vector<JpaFile> jpaFiles = new Vector<JpaFile>(); + + /** + * The "external" Java resource compilation units (source). Populated upon demand. + */ + protected final Vector<JavaResourceCompilationUnit> externalJavaResourceCompilationUnits = new Vector<JavaResourceCompilationUnit>(); + + /** + * The "external" Java resource persistent types (binary). Populated upon demand. + */ + protected final JavaResourcePersistentTypeCache externalJavaResourcePersistentTypeCache; /** * Resource models notify this listener when they change. A project update @@ -160,7 +187,6 @@ public abstract class AbstractJpaProject this.userOverrideDefaultCatalog = config.getUserOverrideDefaultCatalog(); this.userOverrideDefaultSchema = config.getUserOverrideDefaultSchema(); this.discoversAnnotatedClasses = config.discoverAnnotatedClasses(); - this.jpaFiles = this.buildEmptyJpaFiles(); this.modifySharedDocumentCommandExecutor = this.buildModifySharedDocumentCommandExecutor(); @@ -168,10 +194,16 @@ public abstract class AbstractJpaProject // build the JPA files corresponding to the Eclipse project's files this.project.accept(this.buildInitialResourceProxyVisitor(), IResource.NONE); + this.externalJavaResourcePersistentTypeCache = this.buildExternalJavaResourcePersistentTypeCache(); + this.rootContextNode = this.buildRootContextNode(); // "update" the project before returning this.setUpdater_(new SynchronousJpaProjectUpdater(this)); + + // start listening to this cache once the context model has been built + // and all the external types are faulted in + this.externalJavaResourcePersistentTypeCache.addResourceModelListener(this.resourceModelListener); } @Override @@ -184,10 +216,6 @@ public abstract class AbstractJpaProject return this.project; } - protected Vector<JpaFile> buildEmptyJpaFiles() { - return new Vector<JpaFile>(); - } - protected ThreadLocalCommandExecutor buildModifySharedDocumentCommandExecutor() { return new ThreadLocalCommandExecutor(); } @@ -200,6 +228,10 @@ public abstract class AbstractJpaProject return new InitialResourceProxyVisitor(); } + protected JavaResourcePersistentTypeCache buildExternalJavaResourcePersistentTypeCache() { + return new BinaryPersistentTypeCache(this.jpaPlatform.getAnnotationProvider()); + } + protected JpaRootContextNode buildRootContextNode() { return this.getJpaFactory().buildRootContextNode(this); } @@ -213,7 +245,9 @@ public abstract class AbstractJpaProject public boolean visit(IResourceProxy resource) throws CoreException { switch (resource.getType()) { case IResource.ROOT : // shouldn't happen + return true; // visit children case IResource.PROJECT : + return true; // visit children case IResource.FOLDER : return true; // visit children case IResource.FILE : @@ -226,6 +260,21 @@ public abstract class AbstractJpaProject } + // ********** miscellaneous ********** + + /** + * Ignore changes to this collection. Adds can be ignored since they are triggered + * by requests that will, themselves, trigger updates (typically during the + * update of an object that calls a setter with the newly-created resource + * type). Deletes will be accompanied by manual updates. + */ + @Override + protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) { + super.addNonUpdateAspectNamesTo(nonUpdateAspectNames); + nonUpdateAspectNames.add(EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION); + } + + // ********** general queries ********** @Override @@ -255,6 +304,14 @@ public abstract class AbstractJpaProject return this.jpaPlatform; } + @SuppressWarnings("unchecked") + protected Iterable<JavaResourceCompilationUnit> getCombinedJavaResourceCompilationUnits() { + return new CompositeIterable<JavaResourceCompilationUnit>( + this.getInternalJavaResourceCompilationUnits(), + this.getExternalJavaResourceCompilationUnits() + ); + } + // ********** database ********** @@ -334,7 +391,7 @@ public abstract class AbstractJpaProject } - // **************** user override default catalog ********************** + // ********** user override default catalog ********** public String getUserOverrideDefaultCatalog() { return this.userOverrideDefaultCatalog; @@ -348,7 +405,7 @@ public abstract class AbstractJpaProject } - // **************** user override default schema ********************** + // ********** user override default schema ********** public String getUserOverrideDefaultSchema() { return this.userOverrideDefaultSchema; @@ -362,7 +419,7 @@ public abstract class AbstractJpaProject } - // **************** discover annotated classes ***************************** + // ********** discover annotated classes ********** public boolean discoversAnnotatedClasses() { return this.discoversAnnotatedClasses; @@ -379,7 +436,7 @@ public abstract class AbstractJpaProject // ********** JPA files ********** public Iterator<JpaFile> jpaFiles() { - return new CloneIterator<JpaFile>(this.jpaFiles); // read-only + return this.getJpaFiles().iterator(); } protected Iterable<JpaFile> getJpaFiles() { @@ -390,8 +447,8 @@ public abstract class AbstractJpaProject return this.jpaFiles.size(); } - protected Iterator<JpaFile> jpaFiles(final IContentType contentType) { - return new FilteringIterator<JpaFile, JpaFile>(this.jpaFiles()) { + protected Iterable<JpaFile> getJpaFiles(final IContentType contentType) { + return new FilteringIterable<JpaFile, JpaFile>(this.getJpaFiles()) { @Override protected boolean accept(JpaFile jpaFile) { return jpaFile.getContentType().isKindOf(contentType); @@ -453,9 +510,9 @@ public abstract class AbstractJpaProject } return false; } - + /** - * Remove the JPA file and dispose of it + * Stop listening to the JPA file and remove it. */ protected void removeJpaFile(JpaFile jpaFile) { jpaFile.getResourceModel().removeResourceModelListener(this.resourceModelListener); @@ -465,6 +522,107 @@ public abstract class AbstractJpaProject } + // ********** external Java resource persistent types (source or binary) ********** + + protected JavaResourcePersistentType buildPersistableExternalJavaResourcePersistentType(String typeName) { + IType jdtType = this.findType(typeName); + return (jdtType == null) ? null : this.buildPersistableExternalJavaResourcePersistentType(jdtType); + } + + protected IType findType(String typeName) { + try { + return this.getJavaProject().findType(typeName); + } catch (JavaModelException ex) { + return null; // ignore exception? + } + } + + protected JavaResourcePersistentType buildPersistableExternalJavaResourcePersistentType(IType jdtType) { + JavaResourcePersistentType jrpt = this.buildExternalJavaResourcePersistentType(jdtType); + return ((jrpt != null) && jrpt.isPersistable()) ? jrpt : null; + } + + protected JavaResourcePersistentType buildExternalJavaResourcePersistentType(IType jdtType) { + return jdtType.isBinary() ? + this.buildBinaryExternalJavaResourcePersistentType(jdtType) : + this.buildSourceExternalJavaResourcePersistentType(jdtType); + } + + protected JavaResourcePersistentType buildBinaryExternalJavaResourcePersistentType(IType jdtType) { + return this.externalJavaResourcePersistentTypeCache.addPersistentType(jdtType); + } + + protected JavaResourcePersistentType buildSourceExternalJavaResourcePersistentType(IType jdtType) { + String jdtTypeName = jdtType.getFullyQualifiedName(); + JavaResourceCompilationUnit jrcu = this.addExternalJavaResourceCompilationUnit(jdtType.getCompilationUnit()); + for (Iterator<JavaResourcePersistentType> stream = jrcu.persistentTypes(); stream.hasNext(); ) { + JavaResourcePersistentType jrpt = stream.next(); + if (jrpt.getQualifiedName().equals(jdtTypeName)) { + return jrpt; + } + } + // seems like we should never get here... + JptCorePlugin.log("missing type: " + jdtTypeName); //$NON-NLS-1$ + return null; + } + + + // ********** external Java resource persistent types (binary) ********** + + public JavaResourcePersistentTypeCache getExternalJavaResourcePersistentTypeCache() { + return this.externalJavaResourcePersistentTypeCache; + } + + + // ********** external Java resource compilation units (source) ********** + + public Iterator<JavaResourceCompilationUnit> externalJavaResourceCompilationUnits() { + return this.getExternalJavaResourceCompilationUnits().iterator(); + } + + protected Iterable<JavaResourceCompilationUnit> getExternalJavaResourceCompilationUnits() { + return new CloneIterable<JavaResourceCompilationUnit>(this.externalJavaResourceCompilationUnits); // read-only + } + + public int externalJavaResourceCompilationUnitsSize() { + return this.externalJavaResourceCompilationUnits.size(); + } + + /** + * Add an external Java resource compilation unit. + */ + protected JavaResourceCompilationUnit addExternalJavaResourceCompilationUnit(ICompilationUnit jdtCompilationUnit) { + JavaResourceCompilationUnit jrcu = this.buildJavaResourceCompilationUnit(jdtCompilationUnit); + this.addItemToCollection(jrcu, this.externalJavaResourceCompilationUnits, EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION); + jrcu.addResourceModelListener(this.resourceModelListener); + return jrcu; + } + + protected JavaResourceCompilationUnit buildJavaResourceCompilationUnit(ICompilationUnit jdtCompilationUnit) { + return new SourceCompilationUnit( + jdtCompilationUnit, + this.jpaPlatform.getAnnotationProvider(), + this.jpaPlatform.getAnnotationEditFormatter(), + this.modifySharedDocumentCommandExecutor + ); + } + + protected boolean removeExternalJavaResourceCompilationUnit(IFile file) { + for (JavaResourceCompilationUnit jrcu : this.getExternalJavaResourceCompilationUnits()) { + if (jrcu.getFile().equals(file)) { + this.removeExternalJavaResourceCompilationUnit(jrcu); + return true; + } + } + return false; + } + + protected void removeExternalJavaResourceCompilationUnit(JavaResourceCompilationUnit jrcu) { + jrcu.removeResourceModelListener(this.resourceModelListener); + this.removeItemFromCollection(jrcu, this.externalJavaResourceCompilationUnits, EXTERNAL_JAVA_RESOURCE_COMPILATION_UNITS_COLLECTION); + } + + // ********** context model ********** public JpaRootContextNode getRootContextNode() { @@ -517,10 +675,14 @@ public abstract class AbstractJpaProject } - // ********** Java source classes ********** + // ********** annotated Java source classes ********** public Iterator<String> annotatedClassNames() { - return new TransformationIterator<JavaResourcePersistentType, String>(this.persistedSourceJavaResourcePersistentTypes()) { + return this.getAnnotatedClassNames().iterator(); + } + + protected Iterable<String> getAnnotatedClassNames() { + return new TransformationIterable<JavaResourcePersistentType, String>(this.getPersistedInternalSourceJavaResourcePersistentTypes()) { @Override protected String transform(JavaResourcePersistentType jrpType) { return jrpType.getQualifiedName(); @@ -529,43 +691,46 @@ public abstract class AbstractJpaProject } /** - * return only those "persisted" Java resource persistent types that are + * return only those valid "persisted" Java resource persistent types that are * part of the JPA project, ignoring those in JARs referenced in persistence.xml + * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jpt.core.internal.utility.jdt.JPTTools.TypeAdapter) */ - protected Iterator<JavaResourcePersistentType> persistedSourceJavaResourcePersistentTypes() { - return new FilteringIterator<JavaResourcePersistentType, JavaResourcePersistentType>(this.persistableSourceJavaResourcePersistentTypes()) { + protected Iterable<JavaResourcePersistentType> getPersistedInternalSourceJavaResourcePersistentTypes() { + return new FilteringIterable<JavaResourcePersistentType, JavaResourcePersistentType>(this.getInternalSourceJavaResourcePersistentTypes()) { @Override protected boolean accept(JavaResourcePersistentType jrpType) { - return jrpType.isPersisted(); // i.e. the type has a type mapping annotation + return jrpType.isPersistable() && jrpType.isPersisted(); // i.e. the type is valid and has a type mapping annotation } }; } /** - * return only those "persistable" Java resource persistent types that are + * return only those Java resource persistent types that are * part of the JPA project, ignoring those in JARs referenced in persistence.xml - * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jdt.core.dom.ITypeBinding) */ - protected Iterator<JavaResourcePersistentType> persistableSourceJavaResourcePersistentTypes() { - return new CompositeIterator<JavaResourcePersistentType>(this.persistableSourceJavaResourcePersistentTypeIterators()); + protected Iterable<JavaResourcePersistentType> getInternalSourceJavaResourcePersistentTypes() { + return new CompositeIterable<JavaResourcePersistentType>(this.getInternalSourceJavaResourcePersistentTypeSets()); } /** - * return only those "persistable" Java resource persistent types that are + * return only those Java resource persistent types that are * part of the JPA project, ignoring those in JARs referenced in persistence.xml - * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jdt.core.dom.ITypeBinding) */ - protected Iterator<Iterator<JavaResourcePersistentType>> persistableSourceJavaResourcePersistentTypeIterators() { - return new TransformationIterator<JavaResourceCompilationUnit, Iterator<JavaResourcePersistentType>>(this.javaResourceCompilationUnits()) { + protected Iterable<Iterable<JavaResourcePersistentType>> getInternalSourceJavaResourcePersistentTypeSets() { + return new TransformationIterable<JavaResourceCompilationUnit, Iterable<JavaResourcePersistentType>>(this.getInternalJavaResourceCompilationUnits()) { @Override - protected Iterator<JavaResourcePersistentType> transform(JavaResourceCompilationUnit compilationUnit) { - return compilationUnit.persistableTypes(); // i.e. only the types that are *allowed* to be mapped + protected Iterable<JavaResourcePersistentType> transform(final JavaResourceCompilationUnit compilationUnit) { + return new Iterable<JavaResourcePersistentType>() { + public Iterator<JavaResourcePersistentType> iterator() { + return compilationUnit.persistentTypes(); // *all* the types in the compilation unit + } + }; } }; } - protected Iterator<JavaResourceCompilationUnit> javaResourceCompilationUnits() { - return new TransformationIterator<JpaFile, JavaResourceCompilationUnit>(this.javaSourceJpaFiles()) { + protected Iterable<JavaResourceCompilationUnit> getInternalJavaResourceCompilationUnits() { + return new TransformationIterable<JpaFile, JavaResourceCompilationUnit>(this.getJavaSourceJpaFiles()) { @Override protected JavaResourceCompilationUnit transform(JpaFile jpaFile) { return (JavaResourceCompilationUnit) jpaFile.getResourceModel(); @@ -576,51 +741,69 @@ public abstract class AbstractJpaProject /** * return JPA files with Java source "content" */ - protected Iterator<JpaFile> javaSourceJpaFiles() { - return this.jpaFiles(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE); + protected Iterable<JpaFile> getJavaSourceJpaFiles() { + return this.getJpaFiles(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE); } // ********** Java resource persistent type look-up ********** public JavaResourcePersistentType getJavaResourcePersistentType(String typeName) { - for (Iterator<JavaResourcePersistentType> stream = this.persistableJavaResourcePersistentTypes(); stream.hasNext(); ) { - JavaResourcePersistentType jrpType = stream.next(); + for (JavaResourcePersistentType jrpType : this.getPersistableJavaResourcePersistentTypes()) { if (jrpType.getQualifiedName().equals(typeName)) { return jrpType; } } - return null; + // if we don't have a type already, try to build new one from the project classpath + return this.buildPersistableExternalJavaResourcePersistentType(typeName); + } + + /** + * return *all* the "persistable" Java resource persistent types, including those in JARs referenced in + * persistence.xml + * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jpt.core.internal.utility.jdt.JPTTools.TypeAdapter) + */ + protected Iterable<JavaResourcePersistentType> getPersistableJavaResourcePersistentTypes() { + return new FilteringIterable<JavaResourcePersistentType, JavaResourcePersistentType>(this.getJavaResourcePersistentTypes()) { + @Override + protected boolean accept(JavaResourcePersistentType jrpType) { + return jrpType.isPersistable(); + } + }; } /** - * return *all* the "persistable" persistent types, including those in JARs referenced in + * return *all* the Java resource persistent types, including those in JARs referenced in * persistence.xml - * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jdt.core.dom.ITypeBinding) */ - protected Iterator<JavaResourcePersistentType> persistableJavaResourcePersistentTypes() { - return new CompositeIterator<JavaResourcePersistentType>(this.persistableJavaResourcePersistentTypeIterators()); + protected Iterable<JavaResourcePersistentType> getJavaResourcePersistentTypes() { + return new CompositeIterable<JavaResourcePersistentType>(this.getJavaResourcePersistentTypeSets()); } /** - * return *all* the "persistable" persistent types, including those in JARs referenced in + * return *all* the Java resource persistent types, including those in JARs referenced in * persistence.xml - * @see org.eclipse.jpt.core.internal.utility.jdt.JPTTools#typeIsPersistable(org.eclipse.jdt.core.dom.ITypeBinding) */ - protected Iterator<Iterator<JavaResourcePersistentType>> persistableJavaResourcePersistentTypeIterators() { - return new TransformationIterator<JavaResourceNode.Root, Iterator<JavaResourcePersistentType>>(this.javaResourceNodeRoots()) { + protected Iterable<Iterable<JavaResourcePersistentType>> getJavaResourcePersistentTypeSets() { + return new TransformationIterable<JavaResourceNode.Root, Iterable<JavaResourcePersistentType>>(this.getJavaResourceNodeRoots()) { @Override - protected Iterator<JavaResourcePersistentType> transform(JavaResourceNode.Root root) { - return root.persistableTypes(); // i.e. only the types that are *allowed* to be mapped + protected Iterable<JavaResourcePersistentType> transform(final JavaResourceNode.Root root) { + return new Iterable<JavaResourcePersistentType>() { + public Iterator<JavaResourcePersistentType> iterator() { + return root.persistentTypes(); // *all* the types held by the root + } + }; } }; } @SuppressWarnings("unchecked") - protected Iterator<JavaResourceNode.Root> javaResourceNodeRoots() { - return new CompositeIterator<JavaResourceNode.Root>( - this.javaResourceCompilationUnits(), - this.javaResourcePackageFragmentRoots() + protected Iterable<JavaResourceNode.Root> getJavaResourceNodeRoots() { + return new CompositeIterable<JavaResourceNode.Root>( + this.getInternalJavaResourceCompilationUnits(), + this.getInternalJavaResourcePackageFragmentRoots(), + this.getExternalJavaResourceCompilationUnits(), + Collections.singleton(this.externalJavaResourcePersistentTypeCache) ); } @@ -634,8 +817,7 @@ public abstract class AbstractJpaProject } protected JavaResourcePackageFragmentRoot getJavaResourcePackageFragmentRoot(IFile jarFile) { - for (Iterator<JavaResourcePackageFragmentRoot> stream = this.javaResourcePackageFragmentRoots(); stream.hasNext(); ) { - JavaResourcePackageFragmentRoot pfr = stream.next(); + for (JavaResourcePackageFragmentRoot pfr : this.getInternalJavaResourcePackageFragmentRoots()) { if (pfr.getFile().equals(jarFile)) { return pfr; } @@ -643,8 +825,8 @@ public abstract class AbstractJpaProject return null; } - protected Iterator<JavaResourcePackageFragmentRoot> javaResourcePackageFragmentRoots() { - return new TransformationIterator<JpaFile, JavaResourcePackageFragmentRoot>(this.jarJpaFiles()) { + protected Iterable<JavaResourcePackageFragmentRoot> getInternalJavaResourcePackageFragmentRoots() { + return new TransformationIterable<JpaFile, JavaResourcePackageFragmentRoot>(this.getJarJpaFiles()) { @Override protected JavaResourcePackageFragmentRoot transform(JpaFile jpaFile) { return (JavaResourcePackageFragmentRoot) jpaFile.getResourceModel(); @@ -655,13 +837,14 @@ public abstract class AbstractJpaProject /** * return JPA files with JAR "content" */ - protected Iterator<JpaFile> jarJpaFiles() { - return this.jpaFiles(JptCorePlugin.JAR_CONTENT_TYPE); + protected Iterable<JpaFile> getJarJpaFiles() { + return this.getJpaFiles(JptCorePlugin.JAR_CONTENT_TYPE); } - // ********** Java change ********** + // ********** Java events ********** + // TODO handle changes to external projects public void javaElementChanged(ElementChangedEvent event) { this.synchWithJavaDelta(event.getDelta()); } @@ -691,30 +874,30 @@ public abstract class AbstractJpaProject } } - // ***** model - protected void javaModelChanged(IJavaElementDelta delta) { - // process the java model's projects - this.synchWithJavaDeltaChildren(delta); - } - protected void synchWithJavaDeltaChildren(IJavaElementDelta delta) { for (IJavaElementDelta child : delta.getAffectedChildren()) { this.synchWithJavaDelta(child); // recurse } } + // ***** model + protected void javaModelChanged(IJavaElementDelta delta) { + // process the java model's projects + this.synchWithJavaDeltaChildren(delta); + } + // ***** project protected void javaProjectChanged(IJavaElementDelta delta) { - if ( ! delta.getElement().equals(this.getJavaProject())) { - return; // ignore - } - // process the java project's package fragment roots this.synchWithJavaDeltaChildren(delta); if (this.classpathHasChanged(delta)) { - // the jars were processed above, now force all the JPA files to update - this.updateFromJava(); + if (delta.getElement().equals(this.getJavaProject())) { + this.update(this.getInternalJavaResourceCompilationUnits()); + } else { + // TODO see if changed project is on our classpath? + this.update(this.getExternalJavaResourceCompilationUnits()); + } } } @@ -722,9 +905,9 @@ public abstract class AbstractJpaProject return BitTools.flagIsSet(delta.getFlags(), IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED); } - protected void updateFromJava() { - for (Iterator<JavaResourceCompilationUnit> stream = this.javaResourceCompilationUnits(); stream.hasNext(); ) { - stream.next().update(); + protected void update(Iterable<JavaResourceCompilationUnit> javaResourceCompilationUnits) { + for (JavaResourceCompilationUnit javaResourceCompilationUnit : javaResourceCompilationUnits) { + javaResourceCompilationUnit.update(); } } @@ -758,10 +941,10 @@ public abstract class AbstractJpaProject protected void javaCompilationUnitChanged(IJavaElementDelta delta) { if (this.javaCompilationUnitDeltaIsRelevant(delta)) { ICompilationUnit compilationUnit = (ICompilationUnit) delta.getElement(); - for (Iterator<JavaResourceCompilationUnit> stream = this.javaResourceCompilationUnits(); stream.hasNext(); ) { - JavaResourceCompilationUnit jrcu = stream.next(); + for (JavaResourceCompilationUnit jrcu : this.getCombinedJavaResourceCompilationUnits()) { if (jrcu.getCompilationUnit().equals(compilationUnit)) { jrcu.update(); + // TODO ? this.resolveJavaTypes(); // might have new member types now... break; // there *shouldn't* be any more... } } @@ -856,27 +1039,41 @@ public abstract class AbstractJpaProject } - // ********** handling resource deltas ********** + // ********** resource events ********** + // TODO need to do the same thing for external projects and compilation units public void projectChanged(IResourceDelta delta) throws CoreException { - ResourceDeltaVisitor resourceDeltaVisitor = this.buildResourceDeltaVisitor(); + if (delta.getResource().equals(this.getProject())) { + this.internalProjectChanged(delta); + } else { + this.externalProjectChanged(delta); + } + } + + protected void internalProjectChanged(IResourceDelta delta) throws CoreException { + ResourceDeltaVisitor resourceDeltaVisitor = this.buildInternalResourceDeltaVisitor(); delta.accept(resourceDeltaVisitor); - if (resourceDeltaVisitor.jpaFilesChanged()) { - for (Iterator<JavaResourceCompilationUnit> stream = this.javaResourceCompilationUnits(); stream.hasNext(); ) { - stream.next().resolveTypes(); - } + // at this point, if we have added and/or removed JpaFiles, an "update" will have been triggered; + // any changes to the resource model during the "resolve" will trigger further "updates"; + // there should be no need to "resolve" external Java types (they can't have references to + // the internal Java types) + if (resourceDeltaVisitor.encounteredSignificantChange()) { + this.resolveInternalJavaTypes(); } - // update JARs??? - // TODO } - protected ResourceDeltaVisitor buildResourceDeltaVisitor() { - return new ResourceDeltaVisitor(); + protected ResourceDeltaVisitor buildInternalResourceDeltaVisitor() { + return new ResourceDeltaVisitor() { + @Override + public boolean fileChangeIsSignificant(IFile file, int deltaKind) { + return AbstractJpaProject.this.synchronizeJpaFiles(file, deltaKind); + } + }; } /** - * resource delta visitor callback - * Return true if a JpaFile was either added or removed + * Internal resource delta visitor callback. + * Return true if a JpaFile was either added or removed. */ protected boolean synchronizeJpaFiles(IFile file, int deltaKind) { switch (deltaKind) { @@ -885,9 +1082,11 @@ public abstract class AbstractJpaProject case IResourceDelta.REMOVED : return this.removeJpaFile(file); case IResourceDelta.CHANGED : - return this.checkForChangedJpaFile(file); + return this.checkForChangedFileContent(file); case IResourceDelta.ADDED_PHANTOM : + break; // ignore case IResourceDelta.REMOVED_PHANTOM : + break; // ignore default : break; // only worried about added/removed/changed files } @@ -895,7 +1094,7 @@ public abstract class AbstractJpaProject return false; } - protected boolean checkForChangedJpaFile(IFile file) { + protected boolean checkForChangedFileContent(IFile file) { JpaFile jpaFile = this.getJpaFile(file); if (jpaFile == null) { // the file might have changed its content to something that we are interested in @@ -911,15 +1110,101 @@ public abstract class AbstractJpaProject // (e.g. the schema of an orm.xml file changed from JPA to EclipseLink) this.removeJpaFile(jpaFile); this.addJpaFile(file); - return true; + return true; // at the least, we have removed a JPA file } - // ***** inner class + protected void resolveInternalJavaTypes() { + for (JavaResourceCompilationUnit jrcu : this.getInternalJavaResourceCompilationUnits()) { + jrcu.resolveTypes(); + } + } + + protected void externalProjectChanged(IResourceDelta delta) throws CoreException { + if (this.getJavaProject().isOnClasspath(delta.getResource())) { + ResourceDeltaVisitor resourceDeltaVisitor = this.buildExternalResourceDeltaVisitor(); + delta.accept(resourceDeltaVisitor); + // force an "update" here since adding and/or removing an external Java type + // will only trigger an "update" if the "resolve" causes something in the resource model to change + if (resourceDeltaVisitor.encounteredSignificantChange()) { + this.update(); + this.resolveExternalJavaTypes(); + this.resolveInternalJavaTypes(); + } + } + } + + protected ResourceDeltaVisitor buildExternalResourceDeltaVisitor() { + return new ResourceDeltaVisitor() { + @Override + public boolean fileChangeIsSignificant(IFile file, int deltaKind) { + return AbstractJpaProject.this.synchronizeExternalFiles(file, deltaKind); + } + }; + } + + /** + * external resource delta visitor callback + * Return true if a + */ + protected boolean synchronizeExternalFiles(IFile file, int deltaKind) { + switch (deltaKind) { + case IResourceDelta.ADDED : + return this.externalFileAdded(file); + case IResourceDelta.REMOVED : + return this.externalFileRemoved(file); + case IResourceDelta.CHANGED : + break; // ignore + case IResourceDelta.ADDED_PHANTOM : + break; // ignore + case IResourceDelta.REMOVED_PHANTOM : + break; // ignore + default : + break; // only worried about added/removed/changed files + } + + return false; + } + + protected boolean externalFileAdded(IFile file) { + IContentType contentType = PlatformTools.getContentType(file); + if (contentType == null) { + return false; + } + if (contentType.equals(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) { + return true; + } + if (contentType.equals(JptCorePlugin.JAR_CONTENT_TYPE)) { + return true; + } + return false; + } + + protected boolean externalFileRemoved(IFile file) { + IContentType contentType = PlatformTools.getContentType(file); + if (contentType == null) { + return false; + } + if (contentType.equals(JptCorePlugin.JAVA_SOURCE_CONTENT_TYPE)) { + return this.removeExternalJavaResourceCompilationUnit(file); + } + if (contentType.equals(JptCorePlugin.JAR_CONTENT_TYPE)) { + return this.externalJavaResourcePersistentTypeCache.removePersistentTypes(file); + } + return false; + } + + protected void resolveExternalJavaTypes() { + for (JavaResourceCompilationUnit jrcu : this.getExternalJavaResourceCompilationUnits()) { + jrcu.resolveTypes(); + } + } + + // ***** resource delta visitors /** * add or remove a JPA file for every [appropriate] file encountered by the visitor */ - protected class ResourceDeltaVisitor implements IResourceDeltaVisitor { - private boolean jpaFilesChanged = false; + protected abstract class ResourceDeltaVisitor implements IResourceDeltaVisitor { + protected boolean encounteredSignificantChange = false; protected ResourceDeltaVisitor() { super(); @@ -929,25 +1214,34 @@ public abstract class AbstractJpaProject IResource res = delta.getResource(); switch (res.getType()) { case IResource.ROOT : + return true; // visit children case IResource.PROJECT : + return true; // visit children case IResource.FOLDER : return true; // visit children case IResource.FILE : - if (AbstractJpaProject.this.synchronizeJpaFiles((IFile) res, delta.getKind())) { - this.jpaFilesChanged = true; - } + this.fileChanged((IFile) res, delta.getKind()); return false; // no children default : - return false; // no children + return false; // no children (probably shouldn't get here...) } } + protected void fileChanged(IFile file, int deltaKind) { + if (this.fileChangeIsSignificant(file, deltaKind)) { + this.encounteredSignificantChange = true; + } + } + + protected abstract boolean fileChangeIsSignificant(IFile file, int deltaKind); + /** - * Return whether the collection of JPA files was modified while - * traversing the IResourceDelta (i.e. a JPA file was added or removed). + * Return whether the visitor encountered some sort of "significant" + * change while traversing the IResourceDelta + * (e.g. a JPA file was added or removed). */ - protected boolean jpaFilesChanged() { - return this.jpaFilesChanged; + protected boolean encounteredSignificantChange() { + return this.encounteredSignificantChange; } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java index 5e0187d5db..02766a2744 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java @@ -172,11 +172,13 @@ public class GenericJpaModel } /** - * Forward the specified resource delta to the JPA project corresponding - * to the specified Eclipse project. + * Forward the specified resource delta to all our JPA projects; + * they will each determine whether the event is significant. */ - synchronized void projectChanged(IProject project, IResourceDelta delta) throws CoreException { - this.getJpaProjectHolder(project).projectChanged(delta); + synchronized void projectChanged(IResourceDelta delta) throws CoreException { + for (JpaProjectHolder holder : this.jpaProjectHolders) { + holder.projectChanged(delta); + } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java index ccef5cf1d4..b99b9e4498 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java @@ -13,16 +13,16 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.jpt.core.JpaProject; /** - * + * Not much different from the abstract JPA project. */ public class GenericJpaProject extends AbstractJpaProject { - // ********** constructor/initialization ********** public GenericJpaProject(JpaProject.Config config) throws CoreException { super(config); } + } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java index 6517e7210b..4c4893522f 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java @@ -233,14 +233,9 @@ public class JpaModelManager { case IResourceChangeEvent.POST_CHANGE : this.resourcePostChange(event); break; - // we do not listen to these event types - // case IResourceChangeEvent.PRE_CLOSE : // project-only event - // case IResourceChangeEvent.PRE_BUILD : default : break; } - - } /** @@ -288,7 +283,7 @@ public class JpaModelManager { } private void projectChanged(IProject project, IResourceDelta delta) { - this.projectChanged_(project, delta); + this.projectChanged_(delta); this.checkForOpenedProject(project, delta); } @@ -296,9 +291,9 @@ public class JpaModelManager { /** * Checked exceptions bite. */ - private void projectChanged_(IProject project, IResourceDelta delta) { + private void projectChanged_(IResourceDelta delta) { try { - this.jpaModel.projectChanged(project, delta); + this.jpaModel.projectChanged(delta); } catch (CoreException ex) { this.log(ex); // problem traversing the project's resources - not much we can do } @@ -311,16 +306,19 @@ public class JpaModelManager { */ private void checkForOpenedProject(IProject project, IResourceDelta delta) { switch (delta.getKind()) { - case IResourceDelta.CHANGED : + case IResourceDelta.ADDED : // all but project import and rename handled with the facet POST_INSTALL event this.checkDeltaFlagsForOpenedProject(project, delta); + this.checkDeltaFlagsForRenamedProject(project, delta); break; case IResourceDelta.REMOVED : // already handled with the PRE_DELETE event - case IResourceDelta.ADDED : // all but project import and rename handled with the facet POST_INSTALL event + break; + case IResourceDelta.CHANGED : this.checkDeltaFlagsForOpenedProject(project, delta); - this.checkDeltaFlagsForRenamedProject(project, delta); break; case IResourceDelta.ADDED_PHANTOM : // ignore + break; case IResourceDelta.REMOVED_PHANTOM : // ignore + break; default : break; } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaPersistentType.java index f219c2ba5d..cfbe44b1cc 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaPersistentType.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaPersistentType.java @@ -15,6 +15,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.Vector; + import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jdt.core.dom.CompilationUnit; @@ -34,6 +36,8 @@ import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; import org.eclipse.jpt.core.utility.TextRange; import org.eclipse.jpt.utility.Filter; import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.HashBag; +import org.eclipse.jpt.utility.internal.iterables.CloneIterable; import org.eclipse.jpt.utility.internal.iterators.ChainIterator; import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; @@ -52,7 +56,7 @@ public abstract class AbstractJavaPersistentType protected JavaTypeMapping mapping; - protected final List<JavaPersistentAttribute> attributes; + protected final Vector<JavaPersistentAttribute> attributes = new Vector<JavaPersistentAttribute>(); protected PersistentType parentPersistentType; @@ -62,7 +66,6 @@ public abstract class AbstractJavaPersistentType protected AbstractJavaPersistentType(PersistentType.Owner parent, JavaResourcePersistentType jrpt) { super(parent); - this.attributes = new ArrayList<JavaPersistentAttribute>(); this.initialize(jrpt); } @@ -202,6 +205,10 @@ public abstract class AbstractJavaPersistentType return new CloneListIterator<JavaPersistentAttribute>(this.attributes); } + protected Iterable<JavaPersistentAttribute> getAttributes() { + return new CloneIterable<JavaPersistentAttribute>(this.attributes); + } + public int attributesSize() { return this.attributes.size(); } @@ -254,8 +261,8 @@ public abstract class AbstractJavaPersistentType if (values != null) { return values; } - for (Iterator<JavaPersistentAttribute> stream = attributes(); stream.hasNext();) { - values = stream.next().javaCompletionProposals(pos, filter, astRoot); + for (JavaPersistentAttribute attribute : this.getAttributes()) { + values = attribute.javaCompletionProposals(pos, filter, astRoot); if (values != null) { return values; } @@ -269,8 +276,7 @@ public abstract class AbstractJavaPersistentType CompilationUnit astRoot = this.buildASTRoot(); if (this.contains(offset, astRoot)) { - for (Iterator<JavaPersistentAttribute> stream = this.attributes(); stream.hasNext();) { - JavaPersistentAttribute persistentAttribute = stream.next(); + for (JavaPersistentAttribute persistentAttribute : this.getAttributes()) { if (persistentAttribute.contains(offset, astRoot)) { return persistentAttribute; } @@ -353,7 +359,7 @@ public abstract class AbstractJavaPersistentType this.name = this.buildName(); this.initializeAccess(); this.initializeMapping(); - this.initializePersistentAttributes(); + this.initializeAttributes(); } protected void initializeAccess() { @@ -365,13 +371,13 @@ public abstract class AbstractJavaPersistentType this.mapping.initialize(this.resourcePersistentType); } - protected void initializePersistentAttributes() { - for (Iterator<JavaResourcePersistentAttribute> stream = this.persistentAttributes(); stream.hasNext(); ) { + protected void initializeAttributes() { + for (Iterator<JavaResourcePersistentAttribute> stream = this.resourceAttributes(); stream.hasNext(); ) { this.attributes.add(this.createAttribute(stream.next())); } } - protected Iterator<JavaResourcePersistentAttribute> persistentAttributes() { + protected Iterator<JavaResourcePersistentAttribute> resourceAttributes() { return (this.getAccess() == AccessType.PROPERTY) ? this.resourcePersistentType.persistableProperties() : this.resourcePersistentType.persistableFields(); @@ -383,12 +389,20 @@ public abstract class AbstractJavaPersistentType } public void update() { - this.getJpaFile(this.resourcePersistentType.getFile()).addRootStructureNode(this.resourcePersistentType.getQualifiedName(), this); + JpaFile jpaFile = this.getJpaFile(); + if (jpaFile != null) { + // the JPA file can be null if the resource type is "external" + jpaFile.addRootStructureNode(this.resourcePersistentType.getQualifiedName(), this); + } this.setParentPersistentType(this.buildParentPersistentType()); this.setName(this.buildName()); this.updateAccess(); this.updateMapping(); - this.updatePersistentAttributes(); + this.updateAttributes(); + } + + protected JpaFile getJpaFile() { + return this.getJpaFile(this.resourcePersistentType.getFile()); } protected void updateAccess() { @@ -459,33 +473,34 @@ public abstract class AbstractJavaPersistentType return (mappingAnnotation == null) ? null : mappingAnnotation.getAnnotationName(); } - protected void updatePersistentAttributes() { - Collection<JavaPersistentAttribute> contextAttributesToRemove = CollectionTools.collection(attributes()); - Collection<JavaPersistentAttribute> contextAttributesToUpdate = new ArrayList<JavaPersistentAttribute>(); + protected void updateAttributes() { + HashBag<JavaPersistentAttribute> contextAttributesToRemove = CollectionTools.bag(this.attributes(), this.attributesSize()); + ArrayList<JavaPersistentAttribute> contextAttributesToUpdate = new ArrayList<JavaPersistentAttribute>(this.attributesSize()); int resourceIndex = 0; - for (Iterator<JavaResourcePersistentAttribute> stream = this.persistentAttributes(); stream.hasNext(); ) { - JavaResourcePersistentAttribute resourceAttribute = stream.next(); - boolean contextAttributeFound = false; - for (JavaPersistentAttribute contextAttribute : contextAttributesToRemove) { + for (Iterator<JavaResourcePersistentAttribute> resourceAttributes = this.resourceAttributes(); resourceAttributes.hasNext(); ) { + JavaResourcePersistentAttribute resourceAttribute = resourceAttributes.next(); + boolean match = false; + for (Iterator<JavaPersistentAttribute> contextAttributes = contextAttributesToRemove.iterator(); contextAttributes.hasNext(); ) { + JavaPersistentAttribute contextAttribute = contextAttributes.next(); if (contextAttribute.getResourcePersistentAttribute() == resourceAttribute) { - moveAttribute(resourceIndex, contextAttribute); - contextAttributesToRemove.remove(contextAttribute); + this.moveAttribute(resourceIndex, contextAttribute); + contextAttributes.remove(); contextAttributesToUpdate.add(contextAttribute); - contextAttributeFound = true; + match = true; break; } } - if (!contextAttributeFound) { - addAttribute(resourceIndex, createAttribute(resourceAttribute)); + if ( ! match) { + this.addAttribute(resourceIndex, this.createAttribute(resourceAttribute)); } resourceIndex++; } for (JavaPersistentAttribute contextAttribute : contextAttributesToRemove) { - removeAttribute(contextAttribute); + this.removeAttribute(contextAttribute); } - //first handle adding/removing of the persistent attributes, then update the others last, - //this causes less churn in the update process + // handle adding and removing attributes first, update the + // remaining attributes last; this reduces the churn during "update" for (JavaPersistentAttribute contextAttribute : contextAttributesToUpdate) { contextAttribute.update(); } @@ -496,9 +511,9 @@ public abstract class AbstractJavaPersistentType } protected PersistentType buildParentPersistentType() { - HashSet<JavaResourcePersistentType> visitedResourceTypes = new HashSet<JavaResourcePersistentType>(); - visitedResourceTypes.add(this.resourcePersistentType); - PersistentType parent = this.getParent(this.resourcePersistentType.getSuperClassQualifiedName(), visitedResourceTypes); + HashSet<JavaResourcePersistentType> visited = new HashSet<JavaResourcePersistentType>(); + visited.add(this.resourcePersistentType); + PersistentType parent = this.getParent(this.resourcePersistentType.getSuperclassQualifiedName(), visited); if (parent == null) { return null; } @@ -514,19 +529,22 @@ public abstract class AbstractJavaPersistentType * specified name in the persistence unit. If it is not found we use * resource persistent type and look for *its* parent type. * - * 'visitedResourceTypes' is used to detect a cycle in the resource type + * The 'visited' collection is used to detect a cycle in the *resource* type * inheritance hierarchy and prevent the resulting stack overflow. - * Any cycles in the persistent type inheritance hierarchy are handled in + * Any cycles in the *context* type inheritance hierarchy are handled in * #buildParentPersistentType(). */ - protected PersistentType getParent(String typeName, Collection<JavaResourcePersistentType> visitedResourceTypes) { + protected PersistentType getParent(String typeName, Collection<JavaResourcePersistentType> visited) { + if (typeName == null) { + return null; + } JavaResourcePersistentType resourceType = this.getJpaProject().getJavaResourcePersistentType(typeName); - if ((resourceType == null) || visitedResourceTypes.contains(resourceType)) { + if ((resourceType == null) || visited.contains(resourceType)) { return null; } - visitedResourceTypes.add(resourceType); + visited.add(resourceType); PersistentType parent = this.getPersistentType(typeName); - return (parent != null) ? parent : this.getParent(resourceType.getSuperClassQualifiedName(), visitedResourceTypes); // recurse + return (parent != null) ? parent : this.getParent(resourceType.getSuperclassQualifiedName(), visited); // recurse } protected PersistentType getPersistentType(String fullyQualifiedTypeName) { @@ -545,8 +563,13 @@ public abstract class AbstractJavaPersistentType if (reporter.isCancelled()) { throw new ValidationCancelledException(); } - // build the AST root here to pass down - this.validate(messages, reporter, this.buildASTRoot()); + // TODO temporary hack since we don't know yet where to put + // any messages for types in another project (e.g. referenced by + // persistence.xml) + if (this.resourcePersistentType.getFile().getProject().equals(this.getJpaProject().getProject())) { + // build the AST root here to pass down + this.validate(messages, reporter, this.buildASTRoot()); + } } @Override @@ -565,8 +588,8 @@ public abstract class AbstractJavaPersistentType } protected void validateAttributes(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { - for (Iterator<JavaPersistentAttribute> stream = this.attributes(); stream.hasNext(); ) { - this.validateAttribute(stream.next(), reporter, messages, astRoot); + for (JavaPersistentAttribute attribute : this.getAttributes()) { + this.validateAttribute(attribute, reporter, messages, astRoot); } } @@ -588,9 +611,10 @@ public abstract class AbstractJavaPersistentType } public void dispose() { - JpaFile jpaFile = getJpaFile(this.resourcePersistentType.getFile()); + JpaFile jpaFile = this.getJpaFile(); if (jpaFile != null) { // the JPA file can be null if the .java file was deleted + // or the resource type is "external" jpaFile.removeRootStructureNode(this.resourcePersistentType.getQualifiedName()); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJarFile.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJarFile.java index 23fe6d03b1..e412ccbd9f 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJarFile.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJarFile.java @@ -56,7 +56,7 @@ public class GenericJarFile } protected Iterator<JavaPersistentType> buildJavaPersistentTypes() { - return new TransformationIterator<JavaResourcePersistentType, JavaPersistentType>(this.jarResourcePackageFragmentRoot.persistableTypes()) { + return new TransformationIterator<JavaResourcePersistentType, JavaPersistentType>(this.javaResourcePersistentTypes()) { @Override protected JavaPersistentType transform(JavaResourcePersistentType jrpt) { return GenericJarFile.this.buildJavaPersistentType(jrpt); @@ -64,6 +64,14 @@ public class GenericJarFile }; } + /** + * the resource JAR holds only annotated types, so we can use them all for + * building the context types + */ + protected Iterator<JavaResourcePersistentType> javaResourcePersistentTypes() { + return this.jarResourcePackageFragmentRoot.persistentTypes(); + } + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { return this.getJpaFactory().buildJavaPersistentType(this, jrpt); } @@ -157,7 +165,7 @@ public class GenericJarFile HashBag<JavaPersistentType> contextTypesToRemove = CollectionTools.bag(this.javaPersistentTypes(), this.javaPersistentTypes.size()); ArrayList<JavaPersistentType> contextTypesToUpdate = new ArrayList<JavaPersistentType>(this.javaPersistentTypes.size()); - for (Iterator<JavaResourcePersistentType> resourceTypes = this.jarResourcePackageFragmentRoot.persistableTypes(); resourceTypes.hasNext(); ) { + for (Iterator<JavaResourcePersistentType> resourceTypes = this.javaResourcePersistentTypes(); resourceTypes.hasNext(); ) { JavaResourcePersistentType resourceType = resourceTypes.next(); boolean match = false; for (Iterator<JavaPersistentType> contextTypes = contextTypesToRemove.iterator(); contextTypes.hasNext(); ) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmPersistentType.java index 1f0edf463a..12e07cc191 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmPersistentType.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmPersistentType.java @@ -15,6 +15,7 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.ListIterator; + import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jpt.core.JpaStructureNode; import org.eclipse.jpt.core.JptCorePlugin; @@ -40,6 +41,7 @@ import org.eclipse.jpt.core.resource.orm.Attributes; import org.eclipse.jpt.core.resource.orm.XmlAttributeMapping; import org.eclipse.jpt.core.resource.orm.XmlTypeMapping; import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.ClassTools; import org.eclipse.jpt.utility.internal.CollectionTools; import org.eclipse.jpt.utility.internal.iterators.ChainIterator; import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; @@ -77,8 +79,8 @@ public abstract class AbstractOrmPersistentType this.typeMapping = buildTypeMapping(resourceMapping); this.specifiedAccess = this.getResourceAccess(); this.defaultAccess = this.buildDefaultAccess(); - this.initializeJavaPersistentType(); - this.initializeParentPersistentType(); + this.javaPersistentType = this.buildJavaPersistentType(); + this.parentPersistentType = this.buildParentPersistentType(); this.initializePersistentAttributes(); } @@ -111,16 +113,20 @@ public abstract class AbstractOrmPersistentType } public boolean isFor(String typeName) { - String mappingClassName = this.getMapping().getClass_(); - if (mappingClassName == null) { + String className = this.getName(); + if (className == null) { return false; } - if (mappingClassName.equals(typeName)) { + if (className.equals(typeName)) { return true; } - return (this.getDefaultPackage() + '.' + mappingClassName).equals(typeName); + String defaultPackage = this.getDefaultPackage(); + if (defaultPackage == null) { + return false; + } + return (defaultPackage + '.' + className).equals(typeName); } - + protected OrmTypeMapping buildTypeMapping(XmlTypeMapping resourceMapping) { return this.getJpaPlatform().buildOrmTypeMappingFromMappingKey(this, resourceMapping); } @@ -474,11 +480,12 @@ public abstract class AbstractOrmPersistentType } public String getName() { - return getMapping().getClass_(); + return this.getMapping().getClass_(); } public String getShortName(){ - return getName() == null ? null : getName().substring(getName().lastIndexOf('.') + 1); + String className = this.getName(); + return (className == null) ? null : ClassTools.shortNameForClassNamed(className); } public void classChanged(String oldClass, String newClass) { @@ -509,9 +516,9 @@ public abstract class AbstractOrmPersistentType protected AccessType buildDefaultAccess() { if (! getMapping().isMetadataComplete()) { - if (getJavaPersistentType() != null) { + if (this.javaPersistentType != null) { if (javaPersistentTypeHasSpecifiedAccess()) { - return getJavaPersistentType().getAccess(); + return this.javaPersistentType.getAccess(); } if (getParentPersistentType() != null) { return getParentPersistentType().getAccess(); @@ -523,32 +530,38 @@ public abstract class AbstractOrmPersistentType } protected boolean javaPersistentTypeHasSpecifiedAccess() { - return getJavaPersistentType().getSpecifiedAccess() != null || - getJavaPersistentType().hasAnyAttributePersistenceAnnotations(); + return this.javaPersistentType.getSpecifiedAccess() != null || + this.javaPersistentType.hasAnyAttributePersistenceAnnotations(); } - - protected void initializeJavaPersistentType() { - JavaResourcePersistentType jrpt = getJavaResourcePersistentType(); - if (jrpt != null) { - this.javaPersistentType = buildJavaPersistentType(jrpt); - } + + protected JavaPersistentType buildJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + return (jrpt == null) ? null : this.buildJavaPersistentType(jrpt); } protected JavaResourcePersistentType getJavaResourcePersistentType() { - String className = getMapping().getClass_(); + String className = this.getName(); if (className == null) { return null; } className = className.replace('$', '.'); - // try to resolve by only the locally specified name - JavaResourcePersistentType jrpt = this.getJpaProject().getJavaResourcePersistentType(className); + + // first try to resolve using only the locally specified name... + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(className); if (jrpt != null) { return jrpt; } - // try to resolve by prepending the global package name - String packageName = this.getDefaultPackage(); - return this.getJpaProject().getJavaResourcePersistentType(packageName + '.' + className); + // ...then try to resolve by prepending the global package name + String defaultPackage = this.getDefaultPackage(); + if (defaultPackage == null) { + return null; + } + return this.getJavaResourcePersistentType(defaultPackage + '.' + className); + } + + protected JavaResourcePersistentType getJavaResourcePersistentType(String className) { + return this.getJpaProject().getJavaResourcePersistentType(className); } protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { @@ -572,70 +585,70 @@ public abstract class AbstractOrmPersistentType return getAccess(); } - private class SpecifiedPersistentAttributeOwner implements OrmPersistentAttribute.Owner { + protected class SpecifiedPersistentAttributeOwner implements OrmPersistentAttribute.Owner { private JavaPersistentAttribute cachedJavaPersistentAttribute; public JavaPersistentAttribute findJavaPersistentAttribute(OrmPersistentAttribute ormPersistentAttribute) { - JavaPersistentType javaPersistentType = getJavaPersistentType(); - if (javaPersistentType == null) { + if (AbstractOrmPersistentType.this.javaPersistentType == null) { return null; } - if (ormPersistentAttribute.getName() == null) { + String ormName = ormPersistentAttribute.getName(); + if (ormName == null) { return null; } - AccessType ormAccess = AbstractOrmPersistentType.this.getAccess(ormPersistentAttribute); - JavaPersistentAttribute javaPersistentAttribute = findExistingJavaPersistentAttribute(javaPersistentType, ormPersistentAttribute); - if (javaPersistentAttribute != null && ormAccess == javaPersistentAttribute.getAccess()) { - this.cachedJavaPersistentAttribute = null; //we only want to cache the persistent attribute if we build it + AccessType ormAccess = AbstractOrmPersistentType.this.getAccess(ormPersistentAttribute); + + JavaPersistentAttribute javaPersistentAttribute = this.findExistingJavaPersistentAttribute(ormName); + if ((javaPersistentAttribute != null) && (javaPersistentAttribute.getAccess() == ormAccess)) { + this.cachedJavaPersistentAttribute = null; // we only want to cache the persistent attribute if we build it return javaPersistentAttribute; } - //if the javaPersistentAttribute is null, it might exist in a super class that is not persistent, we need to build it ourselves. - //if access is different, we won't be able to find the corresponding java persistent attribute, it won't exist so we build it ourselves - return buildJavaPersistentAttribute(javaPersistentType, ormPersistentAttribute); + + // if 'javaPersistentAttribute' is null, it might exist in a superclass that is not persistent, we need to build it ourselves. + // if access is different, we won't be able to find the corresponding java persistent attribute, it won't exist so we build it ourselves + return this.buildJavaPersistentAttribute(ormName, ormAccess); } - protected JavaPersistentAttribute findExistingJavaPersistentAttribute(JavaPersistentType javaPersistentType, OrmPersistentAttribute ormPersistentAttribute) { - return javaPersistentType.getAttributeNamed(ormPersistentAttribute.getName()); + protected JavaPersistentAttribute findExistingJavaPersistentAttribute(String attributeName) { + return AbstractOrmPersistentType.this.javaPersistentType.getAttributeNamed(attributeName); } - - protected JavaPersistentAttribute buildJavaPersistentAttribute(JavaPersistentType javaPersistentType, OrmPersistentAttribute ormPersistentAttribute) { - AccessType ormAccess = AbstractOrmPersistentType.this.getAccess(ormPersistentAttribute); - String ormName = ormPersistentAttribute.getName(); - //check the already cached javaPersistentAttribute to verify that it still matches name and access type - if (this.cachedJavaPersistentAttribute != null && this.cachedJavaPersistentAttribute.getName().equals(ormName)) { - if (this.cachedJavaPersistentAttribute.getAccess() == ormAccess) { - return this.cachedJavaPersistentAttribute; - } - } - this.cachedJavaPersistentAttribute = null; - JavaResourcePersistentAttribute jrpa = getJavaResourcePersistentAttribute(javaPersistentType.getResourcePersistentType(), ormAccess, ormName); - if (jrpa != null) { - this.cachedJavaPersistentAttribute = getJpaFactory().buildJavaPersistentAttribute(AbstractOrmPersistentType.this, jrpa); - } - else { - this.cachedJavaPersistentAttribute = null; + + protected JavaPersistentAttribute buildJavaPersistentAttribute(String ormName, AccessType ormAccess) { + JavaResourcePersistentAttribute jrpa = this.getJavaResourcePersistentAttribute(this.getJavaResourcePersistentType(), ormName, ormAccess); + if (this.cachedJavaPersistentAttribute != null && + this.cachedJavaPersistentAttribute.getResourcePersistentAttribute() == jrpa) { + return this.cachedJavaPersistentAttribute; } - return this.cachedJavaPersistentAttribute; + return this.cachedJavaPersistentAttribute = (jrpa == null) ? null : AbstractOrmPersistentType.this.buildJavaPersistentAttribute(jrpa); } - - protected JavaResourcePersistentAttribute getJavaResourcePersistentAttribute(JavaResourcePersistentType javaResourcePersistentType, AccessType ormAccess, String ormName) { - Iterator<JavaResourcePersistentAttribute> javaResourceAttributes = javaResourcePersistentType.persistableFields(); - if (ormAccess == AccessType.PROPERTY) { - javaResourceAttributes = javaResourcePersistentType.persistableProperties(); - } - for (JavaResourcePersistentAttribute jrpa : CollectionTools.iterable(javaResourceAttributes)) { - if (ormName.equals(jrpa.getName())) { + + protected JavaResourcePersistentType getJavaResourcePersistentType() { + return AbstractOrmPersistentType.this.javaPersistentType.getResourcePersistentType(); + } + + protected JavaResourcePersistentAttribute getJavaResourcePersistentAttribute(JavaResourcePersistentType javaResourcePersistentType, String ormName, AccessType ormAccess) { + for (Iterator<JavaResourcePersistentAttribute> stream = this.attributes(javaResourcePersistentType, ormAccess); stream.hasNext(); ) { + JavaResourcePersistentAttribute jrpa = stream.next(); + if (jrpa.getName().equals(ormName)) { return jrpa; } } - JavaResourcePersistentType parent = getParentResourcePersistentType(javaResourcePersistentType); - return parent == null ? null : getJavaResourcePersistentAttribute(parent, ormAccess, ormName); - + // climb up inheritance hierarchy + String superclassName = javaResourcePersistentType.getSuperclassQualifiedName(); + if (superclassName == null) { + return null; + } + JavaResourcePersistentType superclass = AbstractOrmPersistentType.this.getJavaResourcePersistentType(superclassName); + if (superclass == null) { + return null; + } + // recurse + return this.getJavaResourcePersistentAttribute(superclass, ormName, ormAccess); } - - protected JavaResourcePersistentType getParentResourcePersistentType(JavaResourcePersistentType javaResourcePersistentType) { - return getJpaProject().getJavaResourcePersistentType(javaResourcePersistentType.getSuperClassQualifiedName()); + + protected Iterator<JavaResourcePersistentAttribute> attributes(JavaResourcePersistentType javaResourcePersistentType, AccessType ormAccess) { + return (ormAccess == AccessType.PROPERTY) ? javaResourcePersistentType.persistableProperties() : javaResourcePersistentType.persistableFields(); } public void updateJavaPersistentAttribute() { @@ -649,6 +662,10 @@ public abstract class AbstractOrmPersistentType } } + protected JavaPersistentAttribute buildJavaPersistentAttribute(JavaResourcePersistentAttribute jrpa) { + return this.getJpaFactory().buildJavaPersistentAttribute(this, jrpa); + } + protected OrmPersistentAttribute buildVirtualOrmPersistentAttribute(JavaAttributeMapping javaAttributeMapping, XmlAttributeMapping resourceMapping) { return buildOrmPersistentAttribute(buildVirtualPersistentAttributeOwner(javaAttributeMapping.getPersistentAttribute()), resourceMapping); } @@ -692,11 +709,8 @@ public abstract class AbstractOrmPersistentType } protected Iterator<JavaResourcePersistentAttribute> javaPersistentAttributes() { - JavaPersistentType javaPersistentType = getJavaPersistentType(); - if (javaPersistentType != null) { - return javaPersistentAttributes(javaPersistentType.getResourcePersistentType()); - } - return EmptyListIterator.instance(); + return (this.javaPersistentType == null) ? EmptyListIterator.<JavaResourcePersistentAttribute>instance() : + this.javaPersistentAttributes(this.javaPersistentType.getResourcePersistentType()); } protected Iterator<JavaResourcePersistentAttribute> javaPersistentAttributes(JavaResourcePersistentType resourcePersistentType) { @@ -705,11 +719,8 @@ public abstract class AbstractOrmPersistentType resourcePersistentType.persistableFields(); } - protected void initializeParentPersistentType() { - JavaPersistentType javaPersistentType = getJavaPersistentType(); - if (javaPersistentType != null) { - this.parentPersistentType = javaPersistentType.getParentPersistentType(); - } + protected PersistentType buildParentPersistentType() { + return (this.javaPersistentType == null) ? null : this.javaPersistentType.getParentPersistentType(); } public void update() { @@ -722,32 +733,25 @@ public abstract class AbstractOrmPersistentType } protected void updateJavaPersistentType() { - JavaResourcePersistentType jrpt = getJavaResourcePersistentType(); + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); if (jrpt == null) { - setJavaPersistentType(null); - } - else { - if (getJavaPersistentType() != null) { - getJavaPersistentType().update(jrpt); - } - else { - setJavaPersistentType(buildJavaPersistentType(jrpt)); + this.setJavaPersistentType(null); + } else { + if (this.javaPersistentType == null) { + this.setJavaPersistentType(this.buildJavaPersistentType(jrpt)); + } else { + this.javaPersistentType.update(jrpt); } } } protected void updateParentPersistentType() { - JavaPersistentType javaPersistentType = getJavaPersistentType(); - PersistentType parentPersistentType = javaPersistentType == null ? null : javaPersistentType.getParentPersistentType(); - if (parentPersistentType == null) { - setParentPersistentType(null); - } - else if (CollectionTools.contains(parentPersistentType.inheritanceHierarchy(), this)) { - //short-circuit in this case, we have circular inheritance - setParentPersistentType(null); - } - else { - setParentPersistentType(parentPersistentType); + PersistentType ppt = this.buildParentPersistentType(); + // check for circular inheritance + if ((ppt == null) || CollectionTools.contains(ppt.inheritanceHierarchy(), this)) { + this.setParentPersistentType(null); + } else { + this.setParentPersistentType(ppt); } } @@ -879,8 +883,8 @@ public abstract class AbstractOrmPersistentType @Override public void postUpdate() { super.postUpdate(); - if (getJavaPersistentType() != null) { - getJavaPersistentType().postUpdate(); + if (this.javaPersistentType != null) { + this.javaPersistentType.postUpdate(); } getMapping().postUpdate(); } @@ -918,7 +922,7 @@ public abstract class AbstractOrmPersistentType DefaultJpaValidationMessages.buildMessage( IMessage.HIGH_SEVERITY, JpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS, - new String[] {getMapping().getClass_()}, + new String[] {this.getName()}, this, this.getMapping().getClassTextRange() ) @@ -953,8 +957,8 @@ public abstract class AbstractOrmPersistentType } public void dispose() { - if (getJavaPersistentType() != null) { - getJavaPersistentType().dispose(); + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java index 763454bbfa..edfd175bd8 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java @@ -210,15 +210,26 @@ public abstract class AbstractOrmRelationshipMapping<T extends XmlRelationshipMa return null; } - // first try to resolve using only the locally specified name - Entity targetEntity = this.getPersistenceUnit().getEntity(targetEntityName); + // first try to resolve using only the locally specified name... + Entity targetEntity = this.getEntity(targetEntityName); if (targetEntity != null) { return targetEntity; } - // then try to resolve by prepending the global package name - String packageName = this.getPersistentAttribute().getPersistentType().getDefaultPackage(); - return this.getPersistenceUnit().getEntity(packageName + '.' + targetEntityName); + // ...then try to resolve by prepending the global package name + String defaultPackageName = this.getDefaultPackageName(); + if (defaultPackageName == null) { + return null; + } + return this.getEntity(defaultPackageName + '.' + targetEntityName); + } + + protected String getDefaultPackageName() { + return this.getPersistentAttribute().getPersistentType().getDefaultPackage(); + } + + protected Entity getEntity(String typeName) { + return this.getPersistenceUnit().getEntity(typeName); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/AbstractPersistenceUnit.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/AbstractPersistenceUnit.java index 30e1cb2d20..2af400250d 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/AbstractPersistenceUnit.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/AbstractPersistenceUnit.java @@ -10,13 +10,13 @@ package org.eclipse.jpt.core.internal.context.persistence; import java.util.ArrayList; -import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.Vector; + import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jpt.core.JpaStructureNode; import org.eclipse.jpt.core.JptCorePlugin; @@ -805,7 +805,7 @@ public abstract class AbstractPersistenceUnit this.propertyValueChanged(propertyName, value); } - public void propertyRemoved(String propertyName) { + public void propertyRemoved(@SuppressWarnings("unused") String propertyName) { // do nothing, override in subclasses as necessary } @@ -1102,17 +1102,17 @@ public abstract class AbstractPersistenceUnit } protected void updateImpliedClassRefs_() { - ArrayList<ClassRef> impliedRefsToRemove = CollectionTools.list(this.impliedClassRefs(), this.impliedClassRefsSize()); + HashBag<ClassRef> impliedRefsToRemove = CollectionTools.bag(this.impliedClassRefs(), this.impliedClassRefsSize()); ArrayList<ClassRef> impliedRefsToUpdate = new ArrayList<ClassRef>(this.impliedClassRefsSize()); for (Iterator<String> annotatedClassNames = this.getJpaProject().annotatedClassNames(); annotatedClassNames.hasNext(); ) { String annotatedClassName = annotatedClassNames.next(); if ( ! this.specifiesPersistentType(annotatedClassName)) { boolean match = false; - for (Iterator<ClassRef> stream = impliedRefsToRemove.iterator(); stream.hasNext(); ) { - ClassRef classRef = stream.next(); + for (Iterator<ClassRef> classRefs = impliedRefsToRemove.iterator(); classRefs.hasNext(); ) { + ClassRef classRef = classRefs.next(); if (annotatedClassName.equals(classRef.getClassName())) { - stream.remove(); + classRefs.remove(); impliedRefsToUpdate.add(classRef); match = true; break; @@ -1144,28 +1144,29 @@ public abstract class AbstractPersistenceUnit * the same as the source. */ protected void updateProperties() { - Collection<Property> contextPropertiesToRemove = CollectionTools.collection(properties()); + HashBag<Property> contextPropertiesToRemove = CollectionTools.bag(this.properties(), this.propertiesSize()); int resourceIndex = 0; for (Iterator<XmlProperty> xmlProperties = this.xmlProperties(); xmlProperties.hasNext(); ) { XmlProperty xmlProperty = xmlProperties.next(); - boolean contextPropertyFound = false; - for (Property contextProperty : contextPropertiesToRemove) { + boolean match = false; + for (Iterator<Property> contextProperties = contextPropertiesToRemove.iterator(); contextProperties.hasNext();) { + Property contextProperty = contextProperties.next(); if (contextProperty.getXmlProperty() == xmlProperty) { - moveProperty_(resourceIndex, contextProperty); + contextProperties.remove(); + this.moveProperty_(resourceIndex, contextProperty); contextProperty.update(); - contextPropertiesToRemove.remove(contextProperty); - contextPropertyFound = true; + match = true; break; } } - if (!contextPropertyFound) { - addProperty_(resourceIndex, this.buildProperty(xmlProperty)); + if ( ! match) { + this.addProperty_(resourceIndex, this.buildProperty(xmlProperty)); } resourceIndex++; } for (Property contextProperty : contextPropertiesToRemove) { - removeProperty_(contextProperty); + this.removeProperty_(contextProperty); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericClassRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericClassRef.java index f2d9660f21..8939bbc8a6 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericClassRef.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericClassRef.java @@ -32,7 +32,7 @@ import org.eclipse.wst.validation.internal.provisional.core.IMessage; import org.eclipse.wst.validation.internal.provisional.core.IReporter; /** - * @see ClassRef + * Context persistence.xml class reference */ public class GenericClassRef extends AbstractXmlContextNode @@ -72,19 +72,9 @@ public class GenericClassRef protected void initialize(XmlJavaClassRef classRef, String typeName) { this.xmlJavaClassRef = classRef; this.className = typeName; - this.initializeJavaPersistentType(); + this.javaPersistentType = this.buildJavaPersistentType(); } - protected void initializeJavaPersistentType() { - if (this.className == null) { - return; - } - JavaResourcePersistentType jrpt = this.getJpaProject().getJavaResourcePersistentType(this.className.replace('$', '.')); - if (jrpt != null) { - this.javaPersistentType = this.buildJavaPersistentType(jrpt); - } - } - @Override public PersistenceUnit getParent() { return (PersistenceUnit) super.getParent(); @@ -179,26 +169,17 @@ public class GenericClassRef this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType); } - - // ********** updating ********** - - public void update(XmlJavaClassRef classRef) { - this.update(classRef, classRef.getJavaClass()); - } - - public void update(String typeName) { - this.update(null, typeName); + protected JavaPersistentType buildJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + return (jrpt == null) ? null : this.buildJavaPersistentType(jrpt); } - protected void update(XmlJavaClassRef classRef, String typeName) { - this.xmlJavaClassRef = classRef; - this.setClassName_(typeName); - this.updateJavaPersistentType(); + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); } protected void updateJavaPersistentType() { - JavaResourcePersistentType jrpt = - this.getJpaProject().getJavaResourcePersistentType(this.className == null ? null : this.className.replace('$', '.')); + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); if (jrpt == null) { if (this.javaPersistentType != null) { this.javaPersistentType.dispose(); @@ -213,8 +194,25 @@ public class GenericClassRef } } - protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { - return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + protected JavaResourcePersistentType getJavaResourcePersistentType() { + return (this.className == null) ? null : this.getJpaProject().getJavaResourcePersistentType(this.className.replace('$', '.')); + } + + + // ********** updating ********** + + public void update(XmlJavaClassRef classRef) { + this.update(classRef, classRef.getJavaClass()); + } + + public void update(String typeName) { + this.update(null, typeName); + } + + protected void update(XmlJavaClassRef classRef, String typeName) { + this.xmlJavaClassRef = classRef; + this.setClassName_(typeName); + this.updateJavaPersistentType(); } @Override diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericJarFileRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericJarFileRef.java index 0a91c962e4..48cac3897b 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericJarFileRef.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericJarFileRef.java @@ -27,7 +27,9 @@ import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.wst.validation.internal.provisional.core.IMessage; import org.eclipse.wst.validation.internal.provisional.core.IReporter; - +/** + * Context JAR file reference (from the persistence unit) + */ public class GenericJarFileRef extends AbstractXmlContextNode implements JarFileRef @@ -149,7 +151,7 @@ public class GenericJarFileRef protected void updateJarFile() { JavaResourcePackageFragmentRoot jrpfr = null; if (! StringTools.stringIsEmpty(this.fileName)) { - jrpfr = this.getJpaProject().getJavaResourcePackageFragmentRoot(this.getFileName()); + jrpfr = this.getJpaProject().getJavaResourcePackageFragmentRoot(this.fileName); } if (jrpfr == null) { if (this.jarFile != null) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java index 72985037da..b2864d8f4d 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java @@ -121,9 +121,6 @@ public class GenericJpaPlatform /** * Return null if we don't have a provider for the specified content type * (since we don't have control over the possible content types). - * NB: We use "is kind of" to match content types; so the search may be - * order-sensitive. - * @see IContentType#isKindOf(IContentType) */ protected JpaResourceModelProvider getResourceModelProvider(IContentType contentType) { for (JpaResourceModelProvider provider : CollectionTools.iterable(resourceModelProviders())) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/AbstractJavaResourceNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/AbstractJavaResourceNode.java index c2803a4cfb..f047f4d8ef 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/AbstractJavaResourceNode.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/AbstractJavaResourceNode.java @@ -76,13 +76,18 @@ public abstract class AbstractJavaResourceNode /** * ignore the aspect name, we notify listeners of *every* change */ - void aspectChanged(@SuppressWarnings("unused") String aspectName) { + protected void aspectChanged(@SuppressWarnings("unused") String aspectName) { this.getRoot().resourceModelChanged(); } // ********** JavaResourceNode implementation ********** + /** + * @see org.eclipse.jpt.core.internal.resource.java.source.SourceCompilationUnit#getRoot() + * @see org.eclipse.jpt.core.internal.resource.java.binary.BinaryPackageFragmentRoot#getRoot() + * @see org.eclipse.jpt.core.internal.resource.java.binary.BinaryPersistentTypeCache#getRoot() + */ public Root getRoot() { return this.parent.getRoot(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryAnnotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryAnnotation.java index e558220bcd..7d5b6bf1ec 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryAnnotation.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryAnnotation.java @@ -55,7 +55,7 @@ public abstract class BinaryAnnotation /** * Return the JDT annotation's member-value pair with the specified name. */ - protected IMemberValuePair getJdtMemberValuePair(String memberName) { + private IMemberValuePair getJdtMemberValuePair(String memberName) { for (IMemberValuePair pair : this.getJdtMemberValuePairs()) { if (pair.getMemberName().equals(memberName)) { return pair; @@ -64,7 +64,7 @@ public abstract class BinaryAnnotation return null; } - protected IMemberValuePair[] getJdtMemberValuePairs() { + private IMemberValuePair[] getJdtMemberValuePairs() { try { return this.jdtAnnotation.getMemberValuePairs(); } catch (JavaModelException ex) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryNode.java index 0b3dd1f01b..2dce18dcf5 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryNode.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryNode.java @@ -13,12 +13,13 @@ import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jpt.core.internal.resource.java.AbstractJavaResourceNode; import org.eclipse.jpt.core.resource.java.JavaResourceCompilationUnit; import org.eclipse.jpt.core.resource.java.JavaResourceNode; -import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; import org.eclipse.jpt.core.utility.TextRange; /** * Binary convenience methods */ +// TODO hopefully this class can go away with some sort of refactoring of the +// source and binary hierarchies... public abstract class BinaryNode extends AbstractJavaResourceNode { @@ -32,11 +33,6 @@ public abstract class BinaryNode // ********** JavaResourceNode implementation ********** - @Override - public JavaResourcePackageFragmentRoot getRoot() { - return (JavaResourcePackageFragmentRoot) super.getRoot(); - } - public void update() { // nothing by default } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragment.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragment.java index df06ef02ca..3b60ab685e 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragment.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragment.java @@ -9,18 +9,18 @@ ******************************************************************************/ package org.eclipse.jpt.core.internal.resource.java.binary; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; import java.util.ListIterator; import java.util.Vector; -import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jpt.core.JptCorePlugin; -import org.eclipse.jpt.core.internal.utility.jdt.JPTTools; import org.eclipse.jpt.core.resource.java.JavaResourceClassFile; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragment; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; @@ -38,8 +38,13 @@ final class BinaryPackageFragment /** JDT package fragment */ private final IPackageFragment packageFragment; - /** class files in the package fragment */ - private final Vector<JavaResourceClassFile> classFiles; + /** + * class files in the package fragment; + * we only hold class files/types that are actually annotated; + * if the unannotated types are needed (e.g. for orm.xml or an + * inheritance tree) they can be discovered on the classpath as needed + */ + private final Vector<JavaResourceClassFile> classFiles = new Vector<JavaResourceClassFile>(); // ********** construction/initialization ********** @@ -47,42 +52,25 @@ final class BinaryPackageFragment BinaryPackageFragment(JavaResourcePackageFragmentRoot parent, IPackageFragment packageFragment) { super(parent); this.packageFragment = packageFragment; - this.classFiles = this.buildClassFiles(); + this.classFiles.addAll(this.buildClassFiles()); } - private Vector<JavaResourceClassFile> buildClassFiles() { - Vector<JavaResourceClassFile> result = new Vector<JavaResourceClassFile>(); - for (IJavaElement child : this.getJDTChildren()) { - IClassFile classFile = (IClassFile) child; - IType type = this.findType(classFile); - if (this.typeIsPersistable(type)) { // we only hold persistable types - result.add(new BinaryClassFile(this, classFile, type)); + private Collection<JavaResourceClassFile> buildClassFiles() { + IJavaElement[] children = this.getJDTChildren(); + ArrayList<JavaResourceClassFile> result = new ArrayList<JavaResourceClassFile>(children.length); + for (IJavaElement child : children) { + IClassFile jdtClassFile = (IClassFile) child; + IType jdtType = jdtClassFile.getType(); + if (BinaryPersistentType.typeIsPersistable(jdtType)) { + JavaResourceClassFile classFile = new BinaryClassFile(this, jdtClassFile, jdtType); + if (classFile.getPersistentType().isPersisted()) { // we only hold annotated types + result.add(classFile); + } } } return result; } - /** - * Return the JDT type corresponding to the specified class file - * by searching the Java project's build path; as opposed to taking - * the type directly from the class file, since another type with the - * same name *may* precede the class file on the build path. - */ - private IType findType(IClassFile classFile) { - IType type = classFile.getType(); - try { - return type.getJavaProject().findType(type.getFullyQualifiedName(), (IProgressMonitor) null); - } catch (JavaModelException ex) { - return null; // ignore exception? - } - } - - private boolean typeIsPersistable(IType type) { - return (type != null) - && type.exists() - && JPTTools.typeIsPersistable(new JPTToolsAdapter(type)); - } - // ********** JarResourceNode implementation ********** @@ -108,11 +96,11 @@ final class BinaryPackageFragment return this.classFiles.size(); } - public Iterator<JavaResourcePersistentType> persistableTypes() { + public Iterator<JavaResourcePersistentType> persistedTypes() { return new TransformationIterator<JavaResourceClassFile, JavaResourcePersistentType>(this.classFiles()) { @Override protected JavaResourcePersistentType transform(JavaResourceClassFile classFile) { - return classFile.getPersistentType(); // we only hold persistable types + return classFile.getPersistentType(); // we only hold annotated types } }; } @@ -135,95 +123,4 @@ final class BinaryPackageFragment sb.append(this.packageFragment.getElementName()); } - - // ********** JPT tools adapter ********** - - /** - * JPTTools needs an adapter so it can work with either an IType - * or an ITypeBinding etc. - */ - protected class JPTToolsAdapter implements JPTTools.TypeAdapter { - private final IType type; - - protected JPTToolsAdapter(IType type) { - super(); - if (type == null) { - throw new NullPointerException(); - } - this.type = type; - } - - public int getModifiers() { - try { - return this.type.getFlags(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return 0; - } - } - - public boolean isAnnotation() { - try { - return this.type.isAnnotation(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isAnonymous() { - try { - return this.type.isAnonymous(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isArray() { - return false; // ??? - } - - public boolean isEnum() { - try { - return this.type.isEnum(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isInterface() { - try { - return this.type.isInterface(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isLocal() { - try { - return this.type.isLocal(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isMember() { - try { - return this.type.isMember(); - } catch (JavaModelException ex) { - JptCorePlugin.log(ex); - return false; - } - } - - public boolean isPrimitive() { - return false; // ??? - } - - } - } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragmentRoot.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragmentRoot.java index 20a384d486..52276c41a0 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragmentRoot.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPackageFragmentRoot.java @@ -9,8 +9,10 @@ ******************************************************************************/ package org.eclipse.jpt.core.internal.resource.java.binary; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; -import java.util.ListIterator; import java.util.Vector; import org.eclipse.core.resources.IFile; @@ -19,13 +21,11 @@ import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jpt.core.JpaAnnotationProvider; -import org.eclipse.jpt.core.JpaResourceModelListener; import org.eclipse.jpt.core.JptCorePlugin; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragment; import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; -import org.eclipse.jpt.utility.internal.ListenerList; -import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; @@ -33,36 +33,29 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; * binary package fragment root */ public final class BinaryPackageFragmentRoot - extends BinaryNode + extends RootBinaryNode implements JavaResourcePackageFragmentRoot { /** JDT package fragment root */ private final IPackageFragmentRoot packageFragmentRoot; - /** pluggable annotation provider */ - private final JpaAnnotationProvider annotationProvider; - - /** listeners notified whenever the resource model changes */ - private final ListenerList<JpaResourceModelListener> resourceModelListenerList; - /** package fragments in the JAR */ - private final Vector<JavaResourcePackageFragment> packageFragments; + private final Vector<JavaResourcePackageFragment> packageFragments = new Vector<JavaResourcePackageFragment>(); // ********** construction/initialization ********** public BinaryPackageFragmentRoot(IPackageFragmentRoot packageFragmentRoot, JpaAnnotationProvider annotationProvider) { - super(null); // the package fragment root is the root of its sub-tree + super(null, annotationProvider); // the package fragment root is the root of its sub-tree this.packageFragmentRoot = packageFragmentRoot; - this.annotationProvider = annotationProvider; - this.resourceModelListenerList = new ListenerList<JpaResourceModelListener>(JpaResourceModelListener.class); - this.packageFragments = this.buildPackageFragments(); + this.packageFragments.addAll(this.buildPackageFragments()); } - private Vector<JavaResourcePackageFragment> buildPackageFragments() { - Vector<JavaResourcePackageFragment> result = new Vector<JavaResourcePackageFragment>(); - for (IJavaElement pf : this.getJDTChildren()) { - result.add(new BinaryPackageFragment(this, (IPackageFragment) pf)); + private Collection<JavaResourcePackageFragment> buildPackageFragments() { + IJavaElement[] jdtChildren = this.getJDTChildren(); + ArrayList<JavaResourcePackageFragment> result = new ArrayList<JavaResourcePackageFragment>(jdtChildren.length); + for (IJavaElement child : jdtChildren) { + result.add(new BinaryPackageFragment(this, (IPackageFragment) child)); } return result; } @@ -71,26 +64,11 @@ public final class BinaryPackageFragmentRoot // ********** overrides ********** @Override - protected boolean requiresParent() { - return false; - } - - @Override - public JavaResourcePackageFragmentRoot getRoot() { - return this; - } - - @Override public IFile getFile() { return (IFile) this.packageFragmentRoot.getResource(); } @Override - public JpaAnnotationProvider getAnnotationProvider() { - return this.annotationProvider; - } - - @Override public void update() { super.update(); this.updatePackageFragments(); @@ -104,41 +82,27 @@ public final class BinaryPackageFragmentRoot // ********** JavaResourceNode.Root implementation ********** - public Iterator<JavaResourcePersistentType> persistableTypes() { - return new CompositeIterator<JavaResourcePersistentType>(this.persistableTypeIterators()); + /** + * NB: we hold only annotated types + */ + public Iterator<JavaResourcePersistentType> persistentTypes() { + return new CompositeIterator<JavaResourcePersistentType>(this.persistedTypeIterators()); } - private Iterator<Iterator<JavaResourcePersistentType>> persistableTypeIterators() { + private Iterator<Iterator<JavaResourcePersistentType>> persistedTypeIterators() { return new TransformationIterator<JavaResourcePackageFragment, Iterator<JavaResourcePersistentType>>(this.packageFragments()) { @Override - protected Iterator<JavaResourcePersistentType> transform(JavaResourcePackageFragment pf) { - return pf.persistableTypes(); + protected Iterator<JavaResourcePersistentType> transform(JavaResourcePackageFragment fragment) { + return fragment.persistedTypes(); } }; } - public void resourceModelChanged() { - for (JpaResourceModelListener listener : this.resourceModelListenerList.getListeners()) { - listener.resourceModelChanged(); - } - } - - - // ********** JpaResourceModel implementation ********** - - public void addResourceModelListener(JpaResourceModelListener listener) { - this.resourceModelListenerList.add(listener); - } - - public void removeResourceModelListener(JpaResourceModelListener listener) { - this.resourceModelListenerList.remove(listener); - } - // ********** JavaResourcePackageFragmentRoot implementation ********** - public ListIterator<JavaResourcePackageFragment> packageFragments() { - return new CloneListIterator<JavaResourcePackageFragment>(this.packageFragments); + public Iterator<JavaResourcePackageFragment> packageFragments() { + return new CloneIterator<JavaResourcePackageFragment>(this.packageFragments); } public int packageFragmentsSize() { @@ -152,11 +116,14 @@ public final class BinaryPackageFragmentRoot try { return this.packageFragmentRoot.getChildren(); } catch (JavaModelException ex) { - JptCorePlugin.log(ex); + // ignore FNFE - which can happen when the workspace is out of synch with O/S file system + if ( ! (ex.getCause() instanceof FileNotFoundException)) { + JptCorePlugin.log(ex); + } return EMPTY_JAVA_ELEMENT_ARRAY; } } - protected static final IJavaElement[] EMPTY_JAVA_ELEMENT_ARRAY = new IJavaElement[0]; + private static final IJavaElement[] EMPTY_JAVA_ELEMENT_ARRAY = new IJavaElement[0]; @Override public void toString(StringBuilder sb) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentAttribute.java index 1a0cdb8319..57856d736e 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentAttribute.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentAttribute.java @@ -72,10 +72,12 @@ final class BinaryPersistentAttribute super(parent, adapter); this.modifiers = this.buildModifiers(); this.typeName = this.buildTypeName(); - this.typeIsInterface = this.buildTypeIsInterface(); - this.typeIsEnum = this.buildTypeIsEnum(); - this.typeSuperclassNames.addAll(this.buildTypeSuperclassNames()); - this.typeInterfaceNames.addAll(this.buildTypeInterfaceNames()); + + IType type = this.getType(); // shouldn't be an array... + this.typeIsInterface = this.buildTypeIsInterface(type); + this.typeIsEnum = this.buildTypeIsEnum(type); + this.typeSuperclassNames.addAll(this.buildTypeSuperclassNames(type)); + this.typeInterfaceNames.addAll(this.buildTypeInterfaceNames(type)); this.typeTypeArgumentNames.addAll(this.buildTypeTypeArgumentNames()); } @@ -87,10 +89,12 @@ final class BinaryPersistentAttribute super.update(); this.setModifiers(this.buildModifiers()); this.setTypeName(this.buildTypeName()); - this.setTypeIsInterface(this.buildTypeIsInterface()); - this.setTypeIsEnum(this.buildTypeIsEnum()); - this.setTypeSuperclassNames(this.buildTypeSuperclassNames()); - this.setTypeInterfaceNames(this.buildTypeInterfaceNames()); + + IType type = this.getType(); // shouldn't be an array... + this.setTypeIsInterface(this.buildTypeIsInterface(type)); + this.setTypeIsEnum(this.buildTypeIsEnum(type)); + this.setTypeSuperclassNames(this.buildTypeSuperclassNames(type)); + this.setTypeInterfaceNames(this.buildTypeInterfaceNames(type)); this.setTypeTypeArgumentNames(this.buildTypeTypeArgumentNames()); } @@ -214,7 +218,7 @@ final class BinaryPersistentAttribute /** * JARs don't have array types; - * also, no generic type arguments + * also, no generic type parameters */ private String buildTypeName() { return convertTypeSignatureToTypeName(this.getTypeSignature()); @@ -231,8 +235,7 @@ final class BinaryPersistentAttribute this.firePropertyChanged(TYPE_IS_INTERFACE_PROPERTY, old, typeIsInterface); } - private boolean buildTypeIsInterface() { - IType type = this.getType(); // shouldn't be an array... + private boolean buildTypeIsInterface(IType type) { try { return (type != null) && type.isInterface(); } catch (JavaModelException ex) { @@ -252,8 +255,7 @@ final class BinaryPersistentAttribute this.firePropertyChanged(TYPE_IS_ENUM_PROPERTY, old, typeIsEnum); } - private boolean buildTypeIsEnum() { - IType type = this.getType(); // shouldn't be an array... + private boolean buildTypeIsEnum(IType type) { try { return (type != null) && type.isEnum(); } catch (JavaModelException ex) { @@ -275,8 +277,7 @@ final class BinaryPersistentAttribute this.synchronizeList(typeSuperclassNames, this.typeSuperclassNames, TYPE_SUPERCLASS_NAMES_COLLECTION); } - private List<String> buildTypeSuperclassNames() { - IType type = this.getType(); + private List<String> buildTypeSuperclassNames(IType type) { if (type == null) { return Collections.emptyList(); } @@ -284,7 +285,7 @@ final class BinaryPersistentAttribute ArrayList<String> names = new ArrayList<String>(); type = this.findSuperclass(type); while (type != null) { - names.add(type.getFullyQualifiedName()); + names.add(type.getFullyQualifiedName()); // no parameters are included here type = this.findSuperclass(type); } return names; @@ -303,8 +304,7 @@ final class BinaryPersistentAttribute this.synchronizeCollection(typeInterfaceNames, this.typeInterfaceNames, TYPE_INTERFACE_NAMES_COLLECTION); } - private Collection<String> buildTypeInterfaceNames() { - IType type = this.getType(); + private Collection<String> buildTypeInterfaceNames(IType type) { if (type == null) { return Collections.emptySet(); } @@ -403,21 +403,6 @@ final class BinaryPersistentAttribute } private static final String[] EMPTY_STRING_ARRAY = new String[0]; - /** - * Strip off the type signature's parameters if present. - * Convert to a readable string. - */ - private static String convertTypeSignatureToTypeName(String typeSignature) { - return (typeSignature == null) ? null : convertTypeSignatureToTypeName_(typeSignature); - } - - /** - * no null check - */ - private static String convertTypeSignatureToTypeName_(String typeSignature) { - return Signature.toString(Signature.getTypeErasure(typeSignature)); - } - private IType findTypeBySignature(String typeSignature) { return (typeSignature == null) ? null : this.findType(convertTypeSignatureToTypeName_(typeSignature)); } @@ -440,16 +425,39 @@ final class BinaryPersistentAttribute } + // ********** adapters ********** - interface Adapter extends BinaryPersistentMember.Adapter { + /** + * Adapt an IField or IMethod. + */ + interface Adapter + extends BinaryPersistentMember.Adapter + { + /** + * Return the field or getter method's "attribute" name + * (e.g. field "foo" -> "foo"; method "getFoo" -> "foo"). + */ String getAttributeName(); + + /** + * Return whether the attribute is a Java field (as opposed to a method). + */ boolean isField(); + + /** + * Return the attribute's type signature. + */ String getTypeSignature() throws JavaModelException; } - static class FieldAdapter implements Adapter { - private final IField field; + /** + * IField adapter + */ + static class FieldAdapter + implements Adapter + { + final IField field; FieldAdapter(IField field) { super(); @@ -461,7 +469,7 @@ final class BinaryPersistentAttribute } public boolean isPersistable() { - return this.field.exists() && JPTTools.fieldIsPersistable(new JPTToolsAdapter(this.field)); + return this.field.exists() && JPTTools.fieldIsPersistable(new JPTToolsAdapter()); } public IAnnotation[] getAnnotations() throws JavaModelException { @@ -484,20 +492,10 @@ final class BinaryPersistentAttribute * JPTTools needs an adapter so it can work with either an IField * or an IVariableBinding etc. */ - static class JPTToolsAdapter implements JPTTools.FieldAdapter { - private final IField field; - - JPTToolsAdapter(IField field) { - super(); - if (field == null) { - throw new NullPointerException(); - } - this.field = field; - } - + class JPTToolsAdapter implements JPTTools.FieldAdapter { public int getModifiers() { try { - return this.field.getFlags(); + return FieldAdapter.this.field.getFlags(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return 0; @@ -508,8 +506,14 @@ final class BinaryPersistentAttribute } - static class MethodAdapter implements Adapter { - private final IMethod method; + /** + * IMethod adapter + */ + static class MethodAdapter + implements Adapter + { + final IMethod method; + static final IMethod[] EMPTY_METHOD_ARRAY = new IMethod[0]; MethodAdapter(IMethod method) { super(); @@ -521,7 +525,7 @@ final class BinaryPersistentAttribute } public boolean isPersistable() { - return JPTTools.methodIsPersistablePropertyGetter(new JPTToolsAdapter(this.method)); + return JPTTools.methodIsPersistablePropertyGetter(new JPTToolsAdapter()); } public IAnnotation[] getAnnotations() throws JavaModelException { @@ -544,37 +548,31 @@ final class BinaryPersistentAttribute * JPTTools needs an adapter so it can work with either an IMethod * or an IMethodBinding etc. */ - static class JPTToolsAdapter implements JPTTools.MethodAdapter { - private final IMethod method; - - JPTToolsAdapter(IMethod method) { + abstract static class AbstractJPTToolsAdapter + implements JPTTools.SimpleMethodAdapter + { + AbstractJPTToolsAdapter() { super(); - if (method == null) { - throw new NullPointerException(); - } - this.method = method; } - public String getName() { - return this.method.getElementName(); - } + abstract IMethod getMethod(); public int getModifiers() { try { - return this.method.getFlags(); + return this.getMethod().getFlags(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return 0; } } - public String getReturnTypeName() { - return Signature.toString(this.getReturnTypeSignature()); + public String getReturnTypeErasureName() { + return convertTypeSignatureToTypeName(this.getReturnTypeSignature()); } private String getReturnTypeSignature() { try { - return this.method.getReturnType(); + return this.getMethod().getReturnType(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return null; @@ -583,34 +581,70 @@ final class BinaryPersistentAttribute public boolean isConstructor() { try { - return this.method.isConstructor(); + return this.getMethod().isConstructor(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return false; } } + } + + static class SimpleJPTToolsAdapter + extends AbstractJPTToolsAdapter + { + private final IMethod method; + + SimpleJPTToolsAdapter(IMethod method) { + super(); + this.method = method; + } + + @Override + IMethod getMethod() { + return this.method; + } + + } + + class JPTToolsAdapter + extends AbstractJPTToolsAdapter + implements JPTTools.MethodAdapter + { + JPTToolsAdapter() { + super(); + } + + @Override + IMethod getMethod() { + return MethodAdapter.this.method; + } + + public String getName() { + return this.getMethod().getElementName(); + } + public int getParametersLength() { - return this.method.getParameterTypes().length; + return this.getMethod().getParameterTypes().length; } - public JPTTools.MethodAdapter getSibling(String name) { + public JPTTools.SimpleMethodAdapter getSibling(String name) { for (IMethod sibling : this.getSiblings()) { if ((sibling.getParameterTypes().length == 0) && sibling.getElementName().equals(name)) { - return new JPTToolsAdapter(sibling); + return new SimpleJPTToolsAdapter(sibling); } } return null; } - public JPTTools.MethodAdapter getSibling(String name, String parameterTypeName) { + public JPTTools.SimpleMethodAdapter getSibling(String name, String parameterTypeErasureName) { for (IMethod sibling : this.getSiblings()) { String[] parmTypes = sibling.getParameterTypes(); if ((parmTypes.length == 1) - && Signature.toString(parmTypes[0]).equals(parameterTypeName) - && sibling.getElementName().equals(name)) { - return new JPTToolsAdapter(sibling); + && sibling.getElementName().equals(name) + && convertTypeSignatureToTypeName(parmTypes[0]).equals(parameterTypeErasureName)) { + return new SimpleJPTToolsAdapter(sibling); } } return null; @@ -618,13 +652,12 @@ final class BinaryPersistentAttribute private IMethod[] getSiblings() { try { - return this.method.getDeclaringType().getMethods(); + return this.getMethod().getDeclaringType().getMethods(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return EMPTY_METHOD_ARRAY; } } - private static final IMethod[] EMPTY_METHOD_ARRAY = new IMethod[0]; } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentMember.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentMember.java index 92e2c59406..00302570b9 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentMember.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentMember.java @@ -16,6 +16,7 @@ import java.util.Vector; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jpt.core.JptCorePlugin; import org.eclipse.jpt.core.resource.java.Annotation; @@ -107,7 +108,7 @@ abstract class BinaryPersistentMember public Annotation getMappingAnnotation() { Iterable<Annotation> annotations = new FixedCloneIterable<Annotation>(this.mappingAnnotations); for (ListIterator<String> stream = this.validMappingAnnotationNames(); stream.hasNext();) { - Annotation annotation = this.getAnnotation(annotations, stream.next()); + Annotation annotation = this.selectAnnotationNamed(annotations, stream.next()); if (annotation != null) { return annotation; } @@ -116,7 +117,7 @@ abstract class BinaryPersistentMember } public Annotation getMappingAnnotation(String annotationName) { - return this.getAnnotation(this.getMappingAnnotations(), annotationName); + return this.selectAnnotationNamed(this.getMappingAnnotations(), annotationName); } private boolean annotationIsValidMappingAnnotation(IAnnotation jdtAnnotation) { @@ -148,7 +149,9 @@ abstract class BinaryPersistentMember return containerAnnotation.nestedAnnotations(); } NestableAnnotation nestableAnnotation = this.getSupportingNestableAnnotation(nestableAnnotationName); - return (nestableAnnotation == null) ? EmptyListIterator.<NestableAnnotation>instance() : new SingleElementListIterator<NestableAnnotation>(nestableAnnotation); + return (nestableAnnotation == null) ? + EmptyListIterator.<NestableAnnotation>instance() : + new SingleElementListIterator<NestableAnnotation>(nestableAnnotation); } private NestableAnnotation getSupportingNestableAnnotation(String annotationName) { @@ -156,7 +159,7 @@ abstract class BinaryPersistentMember } public Annotation getSupportingAnnotation(String annotationName) { - return this.getAnnotation(this.getSupportingAnnotations(), annotationName); + return this.selectAnnotationNamed(this.getSupportingAnnotations(), annotationName); } public Annotation getNonNullSupportingAnnotation(String annotationName) { @@ -203,11 +206,11 @@ abstract class BinaryPersistentMember // ********** miscellaneous ********** - public IMember getMember() { + IMember getMember() { return this.adapter.getMember(); } - private Annotation getAnnotation(Iterable<Annotation> annotations, String annotationName) { + private Annotation selectAnnotationNamed(Iterable<Annotation> annotations, String annotationName) { for (Annotation annotation : annotations) { if (annotation.getAnnotationName().equals(annotationName)) { return annotation; @@ -228,6 +231,21 @@ abstract class BinaryPersistentMember }; } + /** + * Strip off the type signature's parameters if present. + * Convert to a readable string. + */ + static String convertTypeSignatureToTypeName(String typeSignature) { + return (typeSignature == null) ? null : convertTypeSignatureToTypeName_(typeSignature); + } + + /** + * no null check + */ + static String convertTypeSignatureToTypeName_(String typeSignature) { + return Signature.toString(Signature.getTypeErasure(typeSignature)); + } + private IAnnotation[] getJdtAnnotations() { try { return this.adapter.getAnnotations(); @@ -242,8 +260,20 @@ abstract class BinaryPersistentMember // ********** IMember adapter ********** interface Adapter { + /** + * Return the adapter's JDT member (IType, IField, IMethod). + */ IMember getMember(); + + /** + * Return whether the adapter's member is "persistable" + * (i.e. according to the JPA spec the member can be mapped) + */ boolean isPersistable(); + + /** + * Return the adapter's member's JDT annotations. + */ IAnnotation[] getAnnotations() throws JavaModelException; } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentType.java index 4df1330f3a..b652e88abe 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentType.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentType.java @@ -24,7 +24,7 @@ import org.eclipse.jpt.core.JptCorePlugin; import org.eclipse.jpt.core.internal.utility.jdt.JPTTools; import org.eclipse.jpt.core.resource.java.AccessType; import org.eclipse.jpt.core.resource.java.Annotation; -import org.eclipse.jpt.core.resource.java.JavaResourceClassFile; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; import org.eclipse.jpt.utility.MethodSignature; @@ -44,7 +44,7 @@ final class BinaryPersistentType private String qualifiedName; - private String superClassQualifiedName; + private String superclassQualifiedName; private boolean abstract_; // 'abstract' is a reserved word @@ -57,11 +57,11 @@ final class BinaryPersistentType // ********** construction/initialization ********** - BinaryPersistentType(JavaResourceClassFile parent, IType type) { + BinaryPersistentType(JavaResourceNode parent, IType type) { super(parent, new TypeAdapter(type)); this.name = this.buildName(); this.qualifiedName = this.buildQualifiedName(); - this.superClassQualifiedName = this.buildSuperClassQualifiedName(); + this.superclassQualifiedName = this.buildSuperclassQualifiedName(); this.abstract_ = this.buildAbstract(); this.fields = this.buildFields(); this.methods = this.buildMethods(); @@ -77,10 +77,11 @@ final class BinaryPersistentType super.update(); this.setName(this.buildName()); this.setQualifiedName(this.buildQualifiedName()); - this.setSuperClassQualifiedName(this.buildSuperClassQualifiedName()); + this.setSuperclassQualifiedName(this.buildSuperclassQualifiedName()); this.setAbstract(this.buildAbstract()); this.updateFields(); this.updateMethods(); + // need to wait until everything is updated to calculate 'access' this.setAccess(this.buildAccess()); } @@ -157,23 +158,27 @@ final class BinaryPersistentType } private String buildQualifiedName() { - return this.getMember().getFullyQualifiedName(); + return this.getMember().getFullyQualifiedName(); // no parameters are included here } // ***** superclass qualified name - public String getSuperClassQualifiedName() { - return this.superClassQualifiedName; + public String getSuperclassQualifiedName() { + return this.superclassQualifiedName; } - private void setSuperClassQualifiedName(String superClassQualifiedName) { - String old = this.superClassQualifiedName; - this.superClassQualifiedName = superClassQualifiedName; - this.firePropertyChanged(SUPER_CLASS_QUALIFIED_NAME_PROPERTY, old, superClassQualifiedName); + private void setSuperclassQualifiedName(String superclassQualifiedName) { + String old = this.superclassQualifiedName; + this.superclassQualifiedName = superclassQualifiedName; + this.firePropertyChanged(SUPERCLASS_QUALIFIED_NAME_PROPERTY, old, superclassQualifiedName); } - private String buildSuperClassQualifiedName() { + private String buildSuperclassQualifiedName() { + return convertTypeSignatureToTypeName(this.getSuperclassTypeSignature()); + } + + private String getSuperclassTypeSignature() { try { - return this.getMember().getSuperclassName(); + return this.getMember().getSuperclassTypeSignature(); } catch (JavaModelException ex) { JptCorePlugin.log(ex); return null; @@ -397,6 +402,8 @@ final class BinaryPersistentType } + // ********** IType adapter ********** + static class TypeAdapter implements Adapter { private final IType type; @@ -420,6 +427,106 @@ final class BinaryPersistentType } + // ********** "persistable" check ********** + + static boolean typeIsPersistable(IType type) { + return (type != null) + && type.exists() + && JPTTools.typeIsPersistable(new JPTToolsAdapter(type)); + } + + + // ********** JPT tools adapter ********** + + /** + * JPTTools needs an adapter so it can work with either an IType + * or an ITypeBinding etc. + */ + static class JPTToolsAdapter implements JPTTools.TypeAdapter { + private final IType type; + + protected JPTToolsAdapter(IType type) { + super(); + if (type == null) { + throw new NullPointerException(); + } + this.type = type; + } + + public int getModifiers() { + try { + return this.type.getFlags(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return 0; + } + } + + public boolean isAnnotation() { + try { + return this.type.isAnnotation(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isAnonymous() { + try { + return this.type.isAnonymous(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isArray() { + return false; // ??? + } + + public boolean isEnum() { + try { + return this.type.isEnum(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isInterface() { + try { + return this.type.isInterface(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isLocal() { + try { + return this.type.isLocal(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isMember() { + try { + return this.type.isMember(); + } catch (JavaModelException ex) { + JptCorePlugin.log(ex); + return false; + } + } + + public boolean isPrimitive() { + return false; // ??? + } + + } + + // ********** unsupported JavaResourcePersistentType implementation ********** public Iterator<JavaResourcePersistentType> types() { @@ -434,8 +541,4 @@ final class BinaryPersistentType throw new UnsupportedOperationException(); } - public Iterator<JavaResourcePersistentType> allPersistableTypes() { - throw new UnsupportedOperationException(); - } - } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentTypeCache.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentTypeCache.java new file mode 100644 index 0000000000..70dbb73433 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentTypeCache.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2009 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.binary; + +import java.util.Iterator; +import java.util.Vector; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.core.JpaAnnotationProvider; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentTypeCache; +import org.eclipse.jpt.utility.internal.iterables.CloneIterable; +import org.eclipse.jpt.utility.internal.iterables.TransformationIterable; +import org.eclipse.jpt.utility.internal.StringTools; + +/** + * cache used to hold binary "external" Java resource persistent types + * (typically derived from JARs on the project's build path) + */ +public final class BinaryPersistentTypeCache + extends RootBinaryNode + implements JavaResourcePersistentTypeCache +{ + /** populated on-demand */ + private final Vector<Entry> entries = new Vector<Entry>(); + + + // ********** construction ********** + + public BinaryPersistentTypeCache(JpaAnnotationProvider annotationProvider) { + super(null, annotationProvider); + } + + + // ********** JavaResourceNode.Root implementation ********** + + public Iterator<JavaResourcePersistentType> persistentTypes() { + return this.getPersistentTypes().iterator(); + } + + private Iterable<JavaResourcePersistentType> getPersistentTypes() { + return new TransformationIterable<Entry, JavaResourcePersistentType>(this.getEntries()) { + @Override + protected JavaResourcePersistentType transform(Entry entry) { + return entry.persistentType; + } + }; + } + + private Iterable<Entry> getEntries() { + return new CloneIterable<Entry>(this.entries); + } + + + // ********** JavaResourcePersistentTypeCache implementation ********** + + public int persistentTypesSize() { + return this.entries.size(); + } + + public JavaResourcePersistentType addPersistentType(IType jdtType) { + Entry entry = this.buildEntry(jdtType); + this.entries.add(entry); + this.fireItemAdded(PERSISTENT_TYPES_COLLECTION, entry.persistentType); + return entry.persistentType; + } + + private Entry buildEntry(IType jdtType) { + return new Entry(this.buildPersistentType(jdtType), jdtType.getResource()); + } + + private JavaResourcePersistentType buildPersistentType(IType jdtType) { + return new BinaryPersistentType(this, jdtType); + } + + public boolean removePersistentTypes(IFile jarFile) { + boolean modified = false; + for (Entry entry : this.getEntries()) { + IResource resource = entry.resource; + if ((resource != null) && resource.equals(jarFile)) { + this.removeEntry(entry); + modified = true; + } + } + return modified; + } + + private void removeEntry(Entry entry) { + this.entries.remove(entry); + this.fireItemRemoved(PERSISTENT_TYPES_COLLECTION, entry.persistentType); + } + + + // ********** overrides ********** + + @Override + public IFile getFile() { + return null; // ??? + } + + /** + * Ignore changes to this collection. Adds can be ignored since they are triggered + * by requests that will, themselves, trigger updates (typically during the + * update of an object that calls a setter with the newly-created resource + * type). Deletes will be accompanied by manual updates. + */ + @Override + protected void aspectChanged(String aspectName) { + if ((aspectName != null) && ! aspectName.equals(PERSISTENT_TYPES_COLLECTION)) { + super.aspectChanged(aspectName); + } + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.entries); + } + + + // ********** cache entry ********** + + /** + * Associate a persistent type with its resource. + * This will be a JAR in the case of a type loaded from a JAR that is in + * the Eclipse workspace. The resource will be null for a type loaded + * from a JAR or class directory outside of the workspace. + */ + static class Entry { + final JavaResourcePersistentType persistentType; + final IResource resource; + + Entry(JavaResourcePersistentType persistentType, IResource resource) { + super(); + this.persistentType = persistentType; + this.resource = resource; + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.persistentType); + } + + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/RootBinaryNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/RootBinaryNode.java new file mode 100644 index 0000000000..be9981c144 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/RootBinaryNode.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2009 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.binary; + +import org.eclipse.jpt.core.JpaAnnotationProvider; +import org.eclipse.jpt.core.JpaResourceModelListener; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.utility.internal.ListenerList; + +/** + * JAR and external types + */ +abstract class RootBinaryNode + extends BinaryNode + implements JavaResourceNode.Root +{ + /** pluggable annotation provider */ + private final JpaAnnotationProvider annotationProvider; + + /** listeners notified whenever the resource model changes */ + private final ListenerList<JpaResourceModelListener> resourceModelListenerList = new ListenerList<JpaResourceModelListener>(JpaResourceModelListener.class); + + + // ********** construction ********** + + RootBinaryNode(JavaResourceNode parent, JpaAnnotationProvider annotationProvider) { + super(parent); + this.annotationProvider = annotationProvider; + } + + + // ********** overrides ********** + + @Override + protected boolean requiresParent() { + return false; + } + + @Override + public Root getRoot() { + return this; + } + + @Override + public JpaAnnotationProvider getAnnotationProvider() { + return this.annotationProvider; + } + + + // ********** JavaResourceNode.Root implementation ********** + + public void resourceModelChanged() { + for (JpaResourceModelListener listener : this.resourceModelListenerList.getListeners()) { + listener.resourceModelChanged(); + } + } + + + // ********** JpaResourceModel implementation ********** + + public void addResourceModelListener(JpaResourceModelListener listener) { + this.resourceModelListenerList.add(listener); + } + + public void removeResourceModelListener(JpaResourceModelListener listener) { + this.resourceModelListenerList.remove(listener); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/AnnotationContainerTools.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/AnnotationContainerTools.java index ca032d131f..604caaffbd 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/AnnotationContainerTools.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/AnnotationContainerTools.java @@ -9,20 +9,22 @@ ******************************************************************************/ package org.eclipse.jpt.core.internal.resource.java.source; +import java.util.ArrayList; import java.util.List; import java.util.ListIterator; -import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.jdt.core.dom.ArrayInitializer; import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.MarkerAnnotation; +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.JDTTools; import org.eclipse.jpt.core.resource.java.AnnotationContainer; import org.eclipse.jpt.core.resource.java.NestableAnnotation; import org.eclipse.jpt.utility.internal.CollectionTools; -import org.eclipse.jpt.utility.internal.HashBag; /** * Utility methods for manipulating annotation containers. @@ -106,6 +108,9 @@ public final class AnnotationContainerTools { private static <T extends NestableAnnotation> void synchJavaAnnotationsAfterRemove(int index, AnnotationContainer<T> annotationContainer) { List<T> nestableAnnotations = CollectionTools.list(annotationContainer.nestedAnnotations()); for (int i = index; i < nestableAnnotations.size(); i++) { + // the indices are the same because the model annotations are + // already in the proper locations - it's the Java annotations that + // need to be moved to the same location nestableAnnotations.get(i).moveAnnotation(i); } } @@ -125,127 +130,141 @@ public final class AnnotationContainerTools { } /** - * Use the annotation visitor to gather up the nested JDT DOM annotations. + * Return a list of the nested JDT DOM annotations. */ - private static <T extends NestableAnnotation> HashBag<org.eclipse.jdt.core.dom.Annotation> getNestedJdtAnnotations(CompilationUnit astRoot, AnnotationContainer<T> annotationContainer) { - AnnotationVisitor<T> visitor = new AnnotationVisitor<T>(annotationContainer); - annotationContainer.getContainerJdtAnnotation(astRoot).accept(visitor); - return visitor.jdtAnnotations; + private static <T extends NestableAnnotation> ArrayList<Annotation> getNestedJdtAnnotations(CompilationUnit astRoot, AnnotationContainer<T> annotationContainer) { + ArrayList<Annotation> result = new ArrayList<Annotation>(); + Annotation containerJdtAnnotation = annotationContainer.getContainerJdtAnnotation(astRoot); + if (containerJdtAnnotation.isMarkerAnnotation()) { + // no nested annotations + } + else if (containerJdtAnnotation.isSingleMemberAnnotation()) { + if (annotationContainer.getElementName().equals("value")) { //$NON-NLS-1$ + Expression ex = ((SingleMemberAnnotation) containerJdtAnnotation).getValue(); + addJdtAnnotationsTo(ex, annotationContainer.getNestableAnnotationName(), result); + } else { + // no nested annotations + } + } + else if (containerJdtAnnotation.isNormalAnnotation()) { + MemberValuePair pair = getMemberValuePair((NormalAnnotation) containerJdtAnnotation, annotationContainer.getElementName()); + if (pair == null) { + // no nested annotations + } else { + addJdtAnnotationsTo(pair.getValue(), annotationContainer.getNestableAnnotationName(), result); + } + } + return result; } /** - * Update the annotations in the specified annotation container to be in - * synch with those in the specified AST. The appropriate change - * notification will occur. + * Add whatever annotations are represented by the specified expression to + * the specified bag. Add null to the bag for any non-annotation expression. */ - public static <T extends NestableAnnotation> void update(AnnotationContainer<T> annotationContainer, CompilationUnit astRoot) { - HashBag<org.eclipse.jdt.core.dom.Annotation> jdtAnnotations = getNestedJdtAnnotations(astRoot, annotationContainer); - for (ListIterator<T> stream = annotationContainer.nestedAnnotations(); stream.hasNext(); ) { - T nestedAnnotation = stream.next(); - org.eclipse.jdt.core.dom.Annotation jdtAnnotation = nestedAnnotation.getJdtAnnotation(astRoot); - if (jdtAnnotations.isEmpty()) { - // no more JDT DOM annotations - remove the nested annotation at the end of the container's list - int last = annotationContainer.nestedAnnotationsSize() - 1; - T remove = annotationContainer.removeNestedAnnotationInternal(last); - annotationContainer.nestedAnnotationRemoved(last, remove); - } else { - if (jdtAnnotations.remove(jdtAnnotation)) { - // matching JDT DOM annotation found - update the nested annotation - nestedAnnotation.update(astRoot); - } else { - throw new IllegalStateException("invalid nested annotation: " + nestedAnnotation); //$NON-NLS-1$ - } - } + private static void addJdtAnnotationsTo(Expression expression, String annotationName, ArrayList<Annotation> jdtAnnotations) { + if (expression == null) { + jdtAnnotations.add(null); // not sure how we would get here... } - // add nested annotations for the remaining JDT DOM annotations - int start = annotationContainer.nestedAnnotationsSize(); - int size = start + jdtAnnotations.size(); - for (int i = start; i < size; i++) { - T nestedAnnotation = annotationContainer.addNestedAnnotationInternal(); - nestedAnnotation.initialize(astRoot); - annotationContainer.nestedAnnotationAdded(i, nestedAnnotation); + else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) { + addJdtAnnotationsTo((ArrayInitializer) expression, annotationName, jdtAnnotations); + } + else { + jdtAnnotations.add(getJdtAnnotation_(expression, annotationName)); } } - private AnnotationContainerTools() { - super(); - throw new UnsupportedOperationException(); + private static void addJdtAnnotationsTo(ArrayInitializer arrayInitializer, String annotationName, ArrayList<Annotation> jdtAnnotations) { + @SuppressWarnings("unchecked") + List<Expression> expressions = arrayInitializer.expressions(); + for (Expression expression : expressions) { + jdtAnnotations.add(getJdtAnnotation(expression, annotationName)); + } } - - // ********** annotation visitor ********** + /** + * If the specified expression is an annotation with the specified name, return it; + * otherwise return null. + */ + private static Annotation getJdtAnnotation(Expression expression, String annotationName) { + // not sure how the expression could be null... + return (expression == null) ? null : getJdtAnnotation_(expression, annotationName); + } /** - * Gather up the nested JDT annotations. + * pre-condition: expression is not null */ - static class AnnotationVisitor<T extends NestableAnnotation> - extends ASTVisitor - { - final AnnotationContainer<T> annotationContainer; - final HashBag<org.eclipse.jdt.core.dom.Annotation> jdtAnnotations = new HashBag<org.eclipse.jdt.core.dom.Annotation>(); - - AnnotationVisitor(AnnotationContainer<T> annotationContainer) { - super(); - this.annotationContainer = annotationContainer; + private static Annotation getJdtAnnotation_(Expression expression, String annotationName) { + switch (expression.getNodeType()) { + case ASTNode.NORMAL_ANNOTATION: + case ASTNode.SINGLE_MEMBER_ANNOTATION: + case ASTNode.MARKER_ANNOTATION: + Annotation jdtAnnotation = (Annotation) expression; + if (getQualifiedName(jdtAnnotation).equals(annotationName)) { + return jdtAnnotation; + } + return null; + default: + return null; } + } - /** - * MarkerAnnotation children: - * typeName - Name - * we probably don't need to visit a MarkerAnnotation's children - * since it doesn't hold anything interesting... - */ - @Override - public boolean visit(MarkerAnnotation node) { - return this.visit_(node); + private static String getQualifiedName(Annotation jdtAnnotation) { + ITypeBinding typeBinding = jdtAnnotation.resolveTypeBinding(); + if (typeBinding != null) { + String resolvedName = typeBinding.getQualifiedName(); + if (resolvedName != null) { + return resolvedName; + } } + return jdtAnnotation.getTypeName().getFullyQualifiedName(); + } - /** - * SingleMemberAnnotation children: - * typeName - Name - * value - Expression (which can be an Annotation) - */ - @Override - public boolean visit(SingleMemberAnnotation node) { - return this.visit_(node); + private static MemberValuePair getMemberValuePair(NormalAnnotation annotation, String elementName) { + @SuppressWarnings("unchecked") + List<MemberValuePair> pairs = annotation.values(); + for (MemberValuePair pair : pairs) { + if (pair.getName().getFullyQualifiedName().equals(elementName)) { + return pair; + } } + return null; + } - /** - * NormalAnnotation children: - * typeName - Name - * values - MemberValuePair - */ - @Override - public boolean visit(NormalAnnotation node) { - return this.visit_(node); - } + /** + * Update the annotations in the specified annotation container to be in + * synch with those in the specified AST. The appropriate change + * notification will occur. + */ + public static <T extends NestableAnnotation> void update(AnnotationContainer<T> annotationContainer, CompilationUnit astRoot) { + ListIterator<Annotation> jdtAnnotations = getNestedJdtAnnotations(astRoot, annotationContainer).listIterator(); - /** - * MemberValuePair children: - * name - SimpleName - * value - Expression (which can be an Annotation) - */ - @Override - public boolean visit(MemberValuePair node) { - // only process the children if the mvp's name matches the container's element name - return node.getName().getFullyQualifiedName().equals(this.annotationContainer.getElementName()); + for (ListIterator<T> nestedAnnotations = annotationContainer.nestedAnnotations(); nestedAnnotations.hasNext(); ) { + T nestedAnnotation = nestedAnnotations.next(); + if (jdtAnnotations.hasNext()) { + // matching JDT DOM annotation is present - update the nested annotation + jdtAnnotations.next(); // maybe someday we can pass this to the update + nestedAnnotation.update(astRoot); + } else { + // no more JDT DOM annotations - remove the nested annotation at the end of the container's list + int last = annotationContainer.nestedAnnotationsSize() - 1; + T remove = annotationContainer.removeNestedAnnotationInternal(last); + annotationContainer.nestedAnnotationRemoved(last, remove); + } } - boolean visit_(org.eclipse.jdt.core.dom.Annotation jdtAnnotation) { - String jdtAnnotationName = JDTTools.resolveAnnotation(jdtAnnotation); - if (jdtAnnotationName == null) { - return false; // unknown annotation - skip its children - } - if (jdtAnnotationName.equals(this.annotationContainer.getContainerAnnotationName())) { - return true; // process the container annotation's children - } - if (jdtAnnotationName.equals(this.annotationContainer.getNestableAnnotationName())) { - this.jdtAnnotations.add(jdtAnnotation); - return false; // no need to visit the nested annotation's children - } - return false; // ignore other annotations + // add nested annotations for the remaining JDT DOM annotations + int i = annotationContainer.nestedAnnotationsSize(); + while (jdtAnnotations.hasNext()) { + jdtAnnotations.next(); // maybe someday we can pass this to the initialize + T nestedAnnotation = annotationContainer.addNestedAnnotationInternal(); + nestedAnnotation.initialize(astRoot); + annotationContainer.nestedAnnotationAdded(i++, nestedAnnotation); } + } + private AnnotationContainerTools() { + super(); + throw new UnsupportedOperationException(); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourceCompilationUnit.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourceCompilationUnit.java index 09db076531..aa00011c21 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourceCompilationUnit.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourceCompilationUnit.java @@ -156,10 +156,13 @@ public final class SourceCompilationUnit // ********** JavaResourceNode.Root implementation ********** - public Iterator<JavaResourcePersistentType> persistableTypes() { + /** + * NB: return *all* the persistent types since we build them all + */ + public Iterator<JavaResourcePersistentType> persistentTypes() { return (this.persistentType == null) ? EmptyIterator.<JavaResourcePersistentType>instance() : - this.persistentType.allPersistableTypes(); + this.persistentType.allTypes(); } public void resourceModelChanged() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentMember.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentMember.java index 1aff593839..36b0bfa143 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentMember.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentMember.java @@ -55,13 +55,13 @@ abstract class SourcePersistentMember<E extends Member> * mapping annotations; no duplicates (java compiler has an error for * duplicates) */ - final Vector<Annotation> mappingAnnotations; + final Vector<Annotation> mappingAnnotations = new Vector<Annotation>(); /** * supporting annotations; no duplicates (java compiler has an error for * duplicates) */ - final Vector<Annotation> supportingAnnotations; + final Vector<Annotation> supportingAnnotations = new Vector<Annotation>(); boolean persistable; @@ -71,8 +71,6 @@ abstract class SourcePersistentMember<E extends Member> SourcePersistentMember(JavaResourceNode parent, E member) { super(parent); this.member = member; - this.mappingAnnotations = new Vector<Annotation>(); - this.supportingAnnotations = new Vector<Annotation>(); } public void initialize(CompilationUnit astRoot) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentType.java index 663c52b25d..13e79c966d 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentType.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentType.java @@ -52,7 +52,7 @@ final class SourcePersistentType private String qualifiedName; - private String superClassQualifiedName; + private String superclassQualifiedName; private boolean abstract_; // 'abstract' is a reserved word @@ -117,7 +117,7 @@ final class SourcePersistentType super.initialize(astRoot); this.name = this.buildName(astRoot); this.qualifiedName = this.buildQualifiedName(astRoot); - this.superClassQualifiedName = this.buildSuperClassQualifiedName(astRoot); + this.superclassQualifiedName = this.buildSuperclassQualifiedName(astRoot); this.abstract_ = this.buildAbstract(astRoot); this.initializeTypes(astRoot); this.initializeFields(astRoot); @@ -190,7 +190,7 @@ final class SourcePersistentType public void resolveTypes(CompilationUnit astRoot) { super.resolveTypes(astRoot); - this.setSuperClassQualifiedName(this.buildSuperClassQualifiedName(astRoot)); + this.setSuperclassQualifiedName(this.buildSuperclassQualifiedName(astRoot)); for (JavaResourcePersistentAttribute field : this.getFields()) { field.resolveTypes(astRoot); @@ -251,17 +251,17 @@ final class SourcePersistentType } // ***** superclass qualified name - public String getSuperClassQualifiedName() { - return this.superClassQualifiedName; + public String getSuperclassQualifiedName() { + return this.superclassQualifiedName; } - private void setSuperClassQualifiedName(String superClassQualifiedName) { - String old = this.superClassQualifiedName; - this.superClassQualifiedName = superClassQualifiedName; - this.firePropertyChanged(SUPER_CLASS_QUALIFIED_NAME_PROPERTY, old, superClassQualifiedName); + private void setSuperclassQualifiedName(String superclassQualifiedName) { + String old = this.superclassQualifiedName; + this.superclassQualifiedName = superclassQualifiedName; + this.firePropertyChanged(SUPERCLASS_QUALIFIED_NAME_PROPERTY, old, superclassQualifiedName); } - private String buildSuperClassQualifiedName(CompilationUnit astRoot) { + private String buildSuperclassQualifiedName(CompilationUnit astRoot) { ITypeBinding binding = this.member.getBinding(astRoot); if (binding == null) { return null; @@ -344,10 +344,6 @@ final class SourcePersistentType return this.persistableMembers(this.types()); } - public Iterator<JavaResourcePersistentType> allPersistableTypes() { - return this.persistableMembers(this.allTypes()); - } - private JavaResourcePersistentType getType(String typeName, int occurrence) { for (JavaResourcePersistentType type : this.getTypes()) { if (type.isFor(typeName, occurrence)) { @@ -491,7 +487,7 @@ final class SourcePersistentType super.update(astRoot); this.setName(this.buildName(astRoot)); this.setQualifiedName(this.buildQualifiedName(astRoot)); - this.setSuperClassQualifiedName(this.buildSuperClassQualifiedName(astRoot)); + this.setSuperclassQualifiedName(this.buildSuperclassQualifiedName(astRoot)); this.setAbstract(this.buildAbstract(astRoot)); this.updateTypes(astRoot); this.updateFields(astRoot); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/PlatformTools.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/PlatformTools.java index adca663831..48bdb82f02 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/PlatformTools.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/PlatformTools.java @@ -33,7 +33,10 @@ public class PlatformTools { try { fileContents = file.getContents(); } catch (CoreException ex) { - JptCorePlugin.log(ex); + // seems like we can ignore any exception that might occur here; + // e.g. we get a FNFE if the workspace is out of synch with the O/S file system + // JptCorePlugin.log(ex); + // look for content type based on the file name only(?) return findContentTypeFor(fileName); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTMethodAttribute.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTMethodAttribute.java index e6add2469e..b233a2a803 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTMethodAttribute.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTMethodAttribute.java @@ -177,10 +177,12 @@ public class JDTMethodAttribute * JPTTools needs an adapter so it can work with either an IMethod * or an IMethodBinding etc. */ - protected static class JPTToolsAdapter implements JPTTools.MethodAdapter { - private final IMethodBinding methodBinding; + protected static class SimpleJPTToolsAdapter + implements JPTTools.SimpleMethodAdapter + { + protected final IMethodBinding methodBinding; - protected JPTToolsAdapter(IMethodBinding methodBinding) { + protected SimpleJPTToolsAdapter(IMethodBinding methodBinding) { super(); if (methodBinding == null) { throw new NullPointerException(); @@ -188,28 +190,38 @@ public class JDTMethodAttribute this.methodBinding = methodBinding; } - public String getName() { - return this.methodBinding.getName(); - } - public int getModifiers() { return this.methodBinding.getModifiers(); } - public String getReturnTypeName() { + public String getReturnTypeErasureName() { ITypeBinding returnType = this.methodBinding.getReturnType(); - return (returnType == null) ? null : returnType.getTypeDeclaration().getQualifiedName(); + return (returnType == null) ? null : returnType.getTypeDeclaration().getErasure().getQualifiedName(); } public boolean isConstructor() { return this.methodBinding.isConstructor(); } + } + + protected static class JPTToolsAdapter + extends SimpleJPTToolsAdapter + implements JPTTools.MethodAdapter + { + protected JPTToolsAdapter(IMethodBinding methodBinding) { + super(methodBinding); + } + + public String getName() { + return this.methodBinding.getName(); + } + public int getParametersLength() { return this.methodBinding.getParameterTypes().length; } - public JPTTools.MethodAdapter getSibling(String name) { + public JPTTools.SimpleMethodAdapter getSibling(String name) { ITypeBinding typeBinding = this.methodBinding.getDeclaringClass(); if (typeBinding == null) { return null; @@ -217,23 +229,23 @@ public class JDTMethodAttribute for (IMethodBinding sibling : typeBinding.getDeclaredMethods()) { if ((sibling.getParameterTypes().length == 0) && sibling.getName().equals(name)) { - return new JPTToolsAdapter(sibling); + return new SimpleJPTToolsAdapter(sibling); } } return null; } - public JPTTools.MethodAdapter getSibling(String name, String parameterTypeName) { + public JPTTools.SimpleMethodAdapter getSibling(String name, String parameterTypeErasureName) { ITypeBinding typeBinding = this.methodBinding.getDeclaringClass(); if (typeBinding == null) { return null; } for (IMethodBinding sibling : typeBinding.getDeclaredMethods()) { - ITypeBinding[] parmTypes = sibling.getParameterTypes(); - if ((parmTypes.length == 1) - && parmTypes[0].getTypeDeclaration().getQualifiedName().equals(parameterTypeName) - && sibling.getName().equals(name)) { - return new JPTToolsAdapter(sibling); + ITypeBinding[] siblingParmTypes = sibling.getParameterTypes(); + if ((siblingParmTypes.length == 1) + && sibling.getName().equals(name) + && siblingParmTypes[0].getTypeDeclaration().getErasure().getQualifiedName().equals(parameterTypeErasureName)) { + return new SimpleJPTToolsAdapter(sibling); } } return null; diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JPTTools.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JPTTools.java index 328b806442..8a41aeab7a 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JPTTools.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JPTTools.java @@ -103,6 +103,10 @@ public class JPTTools { * Adapted to IVariableBinding and IField. */ public interface FieldAdapter { + /** + * Return the field's modifiers. We use these to check whether the + * field is static or transient. + */ int getModifiers(); } @@ -121,7 +125,7 @@ public class JPTTools { return false; } - String returnTypeName = methodAdapter.getReturnTypeName(); + String returnTypeName = methodAdapter.getReturnTypeErasureName(); if (returnTypeName == null) { return false; // DOM method bindings can have a null name } @@ -167,7 +171,7 @@ public class JPTTools { * Return whether the method's modifiers prevent it * from being a getter or setter for a "persistent" property. */ - private static boolean methodHasInvalidModifiers(MethodAdapter methodAdapter) { + private static boolean methodHasInvalidModifiers(SimpleMethodAdapter methodAdapter) { int modifiers = methodAdapter.getModifiers(); if (Modifier.isStatic(modifiers)) { return true; @@ -193,7 +197,7 @@ public class JPTTools { * "is" method. */ private static boolean methodHasValidSiblingIsMethod(MethodAdapter methodAdapter, String capitalizedAttributeName) { - MethodAdapter isMethodAdapter = methodAdapter.getSibling("is" + capitalizedAttributeName); //$NON-NLS-1$ + SimpleMethodAdapter isMethodAdapter = methodAdapter.getSibling("is" + capitalizedAttributeName); //$NON-NLS-1$ return methodIsValidSibling(isMethodAdapter, "boolean"); //$NON-NLS-1$ } @@ -201,8 +205,8 @@ public class JPTTools { * Return whether the method has a sibling "set" method * and that method is valid for a "persistable" property. */ - private static boolean methodHasValidSiblingSetMethod(MethodAdapter methodAdapter, String capitalizedAttributeName, String returnTypeName) { - MethodAdapter setMethodAdapter = methodAdapter.getSibling("set" + capitalizedAttributeName, returnTypeName); //$NON-NLS-1$ + private static boolean methodHasValidSiblingSetMethod(MethodAdapter methodAdapter, String capitalizedAttributeName, String parameterTypeErasureName) { + SimpleMethodAdapter setMethodAdapter = methodAdapter.getSibling("set" + capitalizedAttributeName, parameterTypeErasureName); //$NON-NLS-1$ return methodIsValidSibling(setMethodAdapter, "void"); //$NON-NLS-1$ } @@ -210,7 +214,7 @@ public class JPTTools { * Return whether the specified method is a valid sibling with the * specified return type. */ - private static boolean methodIsValidSibling(MethodAdapter methodAdapter, String returnTypeName) { + private static boolean methodIsValidSibling(SimpleMethodAdapter methodAdapter, String returnTypeName) { if (methodAdapter == null) { return false; } @@ -220,7 +224,7 @@ public class JPTTools { if (methodAdapter.isConstructor()) { return false; } - String rtName = methodAdapter.getReturnTypeName(); + String rtName = methodAdapter.getReturnTypeErasureName(); if (rtName == null) { return false; // DOM method bindings can have a null name } @@ -231,14 +235,59 @@ public class JPTTools { * Queries needed to calculate whether a method is "persistable". * Adapted to IMethodBinding and IMethod. */ - public interface MethodAdapter { - String getName(); + public interface SimpleMethodAdapter { + /** + * Return the method's modifiers. + * We use these to check whether the method is static, final, etc. + */ int getModifiers(); - String getReturnTypeName(); + + /** + * Return the name of the method's return type erasure. + * We use this to check for + * - boolean getters + * - void return types + * - matching getters and setters + */ + String getReturnTypeErasureName(); + + /** + * Return whether the method is a constructor. + */ boolean isConstructor(); + } + + /** + * Queries needed to calculate whether a method is "persistable". + * Adapted to IMethodBinding and IMethod. + */ + public interface MethodAdapter extends SimpleMethodAdapter { + /** + * Return the method's name. + * We use this to determine + * - whether the method is a "getter" + * - the property name implied by the getter's name + */ + String getName(); + + /** + * Return the number of paramters declared by the method. + * We use this to determine whether the method is a "getter". + */ int getParametersLength(); - MethodAdapter getSibling(String name); - MethodAdapter getSibling(String name, String parameterTypeName); + + /** + * Return the method's "sibling" with the specified name and no parameters. + * We use this to find an "is" boolean getter that would take precedence + * over a "get" boolean getter. + */ + SimpleMethodAdapter getSibling(String name); + + /** + * Return the method's "sibling" with the specified name and single parameter. + * We use this to find a matching "setter" for a possible "getter". + */ + SimpleMethodAdapter getSibling(String name, String parameterTypeErasureName); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourceNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourceNode.java index 08e3824b0d..e1bbf444ed 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourceNode.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourceNode.java @@ -19,7 +19,7 @@ import org.eclipse.jpt.core.utility.TextRange; import org.eclipse.jpt.utility.model.Model; /** - * Common interface for Java resource nodes (source code or JAR). + * Common interface for Java resource nodes (source code or binary). * * Provisional API: This interface is part of an interim API that is still * under development and expected to change significantly before reaching @@ -70,10 +70,9 @@ public interface JavaResourceNode interface Root extends JavaResourceNode, JpaResourceModel { /** - * Return the root's "persistable" Java resource types, as defined by the - * JPA spec. + * Return the root's Java resource persistent types. */ - Iterator<JavaResourcePersistentType> persistableTypes(); + Iterator<JavaResourcePersistentType> persistentTypes(); /** * Called (via a hook in change notification) whenever anything in the diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragment.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragment.java index 2bbb5247bf..0aab8379d4 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragment.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragment.java @@ -10,8 +10,6 @@ package org.eclipse.jpt.core.resource.java; import java.util.Iterator; -import java.util.ListIterator; - /** * Java package fragment @@ -28,7 +26,8 @@ public interface JavaResourcePackageFragment /** * Return the package fragment's class files that contain "persistable" types. */ - ListIterator<JavaResourceClassFile> classFiles(); + Iterator<JavaResourceClassFile> classFiles(); + String CLASS_FILES_COLLECTION = "classFiles"; //$NON-NLS-1$ /** * Return the size of the package fragment's class files. @@ -36,9 +35,9 @@ public interface JavaResourcePackageFragment int classFilesSize(); /** - * Return the package fragment's "persistable" resource types, as defined - * by the JPA spec. + * Return the package fragment's Java persistent types. + * Return only the files that are annotated with JPA annotations. */ - Iterator<JavaResourcePersistentType> persistableTypes(); + Iterator<JavaResourcePersistentType> persistedTypes(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragmentRoot.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragmentRoot.java index a3a617c0ac..1d056770f2 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragmentRoot.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePackageFragmentRoot.java @@ -9,8 +9,7 @@ ******************************************************************************/ package org.eclipse.jpt.core.resource.java; -import java.util.ListIterator; - +import java.util.Iterator; /** * Java package fragement root @@ -27,7 +26,8 @@ public interface JavaResourcePackageFragmentRoot /** * Return the package fragment root's package fragments. */ - ListIterator<JavaResourcePackageFragment> packageFragments(); + Iterator<JavaResourcePackageFragment> packageFragments(); + String PACKAGE_FRAGMENTS_COLLECTION = "packageFragments"; //$NON-NLS-1$ /** * Return the size of the package fragment root's package fragments. diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentType.java index b7da39d320..b16376ed0d 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentType.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentType.java @@ -36,10 +36,10 @@ public interface JavaResourcePersistentType String QUALIFIED_NAME_PROPERTY = "qualifiedName"; //$NON-NLS-1$ /** - * Return the fully qualified name of the type's super class. + * Return the fully qualified name of the type's superclass. */ - String getSuperClassQualifiedName(); - String SUPER_CLASS_QUALIFIED_NAME_PROPERTY = "superClassQualifiedName"; //$NON-NLS-1$ + String getSuperclassQualifiedName(); + String SUPERCLASS_QUALIFIED_NAME_PROPERTY = "superclassQualifiedName"; //$NON-NLS-1$ /** * Return whether the type is abstract. @@ -79,12 +79,6 @@ public interface JavaResourcePersistentType */ Iterator<JavaResourcePersistentType> persistableTypes(); - /** - * Return all the "persistable" types (the type itself, its children, its - * grandchildren, etc.) as defined by the JPA spec. - */ - Iterator<JavaResourcePersistentType> allPersistableTypes(); - // ********** fields ********** diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentTypeCache.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentTypeCache.java new file mode 100644 index 0000000000..54f0aa2bf8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentTypeCache.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2009 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.resource.java; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.core.IType; + +/** + * Java persistent type cache - used to hold "external" types + * + * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + */ +public interface JavaResourcePersistentTypeCache + extends JavaResourceNode.Root +{ + + String PERSISTENT_TYPES_COLLECTION = "persistentTypes"; //$NON-NLS-1$ + + /** + * Return the size of the cache's persistent types. + */ + int persistentTypesSize(); + + /** + * Add a Java resource persistent type for the specified JDT type to the + * cache. Return the new type. + */ + JavaResourcePersistentType addPersistentType(IType jdtType); + + /** + * Remove all the persistent types associated with the specified JAR file. + * Return whether any persistent types were removed. + */ + boolean removePersistentTypes(IFile jarFile); + +} |