Skip to main content
summaryrefslogtreecommitdiffstats
path: root/jpa
diff options
context:
space:
mode:
authorbvosburgh2010-04-13 19:02:25 +0000
committerbvosburgh2010-04-13 19:02:25 +0000
commitb1d6030eaef59063c87452d9b42ab6bb951d94dd (patch)
tree58ab1d3169cce8989c5a6660ba662ea2f323b778 /jpa
parenta983b1db0395bc424bf3d818b504ebd62128e769 (diff)
downloadwebtools.dali-b1d6030eaef59063c87452d9b42ab6bb951d94dd.tar.gz
webtools.dali-b1d6030eaef59063c87452d9b42ab6bb951d94dd.tar.xz
webtools.dali-b1d6030eaef59063c87452d9b42ab6bb951d94dd.zip
[305079] canonical metamodel for nested classes
Diffstat (limited to 'jpa')
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java6
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java12
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmIdClassReference.java41
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/AbstractPersistenceUnit.java198
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java62
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java26
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java8
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericMetamodelSynchronizer.java432
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java604
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaPersistentType2_0.java57
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/binary/BinaryPersistentType.java28
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentMember.java6
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/resource/java/source/SourcePersistentType.java74
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTType.java12
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java4
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaProject2_0.java18
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/MetamodelSourceType.java116
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/PersistentType2_0.java28
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/resource/java/JavaResourcePersistentType2_0.java17
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JavaResourcePersistentType.java7
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/utility/BodySourceWriter.java303
-rw-r--r--jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java7
-rw-r--r--jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/IndentingPrintWriter.java (renamed from jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/IndentingPrintWriter.java)14
-rw-r--r--jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java2
-rw-r--r--jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/ClassNameTests.java8
-rw-r--r--jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/IndentingPrintWriterTests.java5
-rw-r--r--jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/model/value/swing/TreeModelAdapterTests.java4
27 files changed, 1349 insertions, 750 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
index 3a24c053f0..bf311dab43 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
@@ -27,6 +27,7 @@ import org.eclipse.jpt.core.context.java.JavaAttributeMapping;
import org.eclipse.jpt.core.context.java.JavaAttributeOverride;
import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer;
import org.eclipse.jpt.core.context.java.JavaBaseColumn;
+import org.eclipse.jpt.core.context.java.JavaBaseColumn.Owner;
import org.eclipse.jpt.core.context.java.JavaBaseJoinColumn;
import org.eclipse.jpt.core.context.java.JavaBasicMapping;
import org.eclipse.jpt.core.context.java.JavaColumn;
@@ -68,7 +69,6 @@ import org.eclipse.jpt.core.context.java.JavaTransientMapping;
import org.eclipse.jpt.core.context.java.JavaTypeMapping;
import org.eclipse.jpt.core.context.java.JavaUniqueConstraint;
import org.eclipse.jpt.core.context.java.JavaVersionMapping;
-import org.eclipse.jpt.core.context.java.JavaBaseColumn.Owner;
import org.eclipse.jpt.core.context.orm.OrmXml;
import org.eclipse.jpt.core.context.persistence.MappingFileRef;
import org.eclipse.jpt.core.context.persistence.PersistenceXml;
@@ -130,8 +130,8 @@ import org.eclipse.jpt.core.internal.jpa2.context.java.NullJavaMapKeyColumn2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.NullJavaOrderColumn2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.NullJavaOrphanRemoval2_0;
import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.Orderable2_0;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheable2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheableHolder2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCollectionTable2_0;
@@ -168,7 +168,7 @@ public abstract class AbstractJpaFactory
return new GenericJpaProject(config);
}
- public PersistentType2_0.MetamodelSynchronizer buildPersistentTypeMetamodelSynchronizer(PersistentType2_0 persistentType) {
+ public MetamodelSourceType.Synchronizer buildMetamodelSynchronizer(MetamodelSourceType sourceType) {
return null;
}
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 fdcfdb67fa..42280b830f 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
@@ -924,7 +924,7 @@ public abstract class AbstractJpaProject
// ********** metamodel **********
- public Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTypes() {
+ public Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTopLevelTypes() {
if (this.metamodelSourceFolderName == null) {
return EmptyIterable.instance();
}
@@ -932,25 +932,23 @@ public abstract class AbstractJpaProject
return new FilteringIterable<JavaResourcePersistentType2_0>(this.getInternalSourceJavaResourcePersistentTypes2_0()) {
@Override
protected boolean accept(JavaResourcePersistentType2_0 jrpt) {
- return jrpt.isGeneratedMetamodel(genSourceFolder);
+ return jrpt.isGeneratedMetamodelTopLevelType(genSourceFolder);
}
};
}
- public JavaResourcePersistentType2_0 getGeneratedMetamodelType(IFile file) {
+ public JavaResourcePersistentType2_0 getGeneratedMetamodelTopLevelType(IFile file) {
JavaResourceCompilationUnit jrcu = this.getJavaResourceCompilationUnit(file);
if (jrcu == null) {
return null; // hmmm...
}
+ // TODO add API to JRCU to get top-level persistent type
Iterator<JavaResourcePersistentType> types = jrcu.persistentTypes();
if ( ! types.hasNext()) {
return null; // no types in the file
}
JavaResourcePersistentType2_0 jrpt = (JavaResourcePersistentType2_0) types.next();
- if (types.hasNext()) {
- return null; // should have only a single type in the file
- }
- return jrpt.isGeneratedMetamodel() ? jrpt : null;
+ return jrpt.isGeneratedMetamodelTopLevelType() ? jrpt : null;
}
protected JavaResourceCompilationUnit getJavaResourceCompilationUnit(IFile file) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmIdClassReference.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmIdClassReference.java
index 34a0624550..5b9a999399 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmIdClassReference.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmIdClassReference.java
@@ -78,15 +78,15 @@ public class GenericOrmIdClassReference
String oldClassName = this.specifiedIdClassName;
this.specifiedIdClassName = newClassName;
if (valuesAreDifferent(oldClassName, newClassName)) {
- if (getIdClassElement() != null) {
- getIdClassElement().setClassName(newClassName);
- if (getIdClassElement().isUnset()) {
+ if (getIdXmlClassRef() != null) {
+ getIdXmlClassRef().setClassName(newClassName);
+ if (getIdXmlClassRef().isUnset()) {
removeIdClassElement();
}
}
else if (newClassName != null) {
addIdClassElement();
- getIdClassElement().setClassName(newClassName);
+ getIdXmlClassRef().setClassName(newClassName);
}
}
firePropertyChanged(SPECIFIED_ID_CLASS_NAME_PROPERTY, oldClassName, newClassName);
@@ -99,11 +99,8 @@ public class GenericOrmIdClassReference
}
protected String buildSpecifiedIdClassName() {
- XmlClassReference element = getIdClassElement();
- if (element != null) {
- return element.getClassName();
- }
- return null;
+ XmlClassReference idXmlClassRef = this.getIdXmlClassRef();
+ return (idXmlClassRef == null) ? null : idXmlClassRef.getClassName();
}
public String getDefaultIdClassName() {
@@ -156,8 +153,8 @@ public class GenericOrmIdClassReference
return (XmlIdClassContainer) getResourceTypeMapping();
}
- protected XmlClassReference getIdClassElement() {
- return getResourceIdClassContainer().getIdClass();
+ protected XmlClassReference getIdXmlClassRef() {
+ return this.getResourceIdClassContainer().getIdClass();
}
protected void addIdClassElement() {
@@ -169,10 +166,17 @@ public class GenericOrmIdClassReference
}
protected JavaResourcePersistentType getResourceIdClass() {
- XmlClassReference element = getIdClassElement();
- String className = (element == null) ?
- null : element.getClassName();
- return getEntityMappings().resolveJavaResourcePersistentType(className);
+ XmlClassReference idXmlClassRef = this.getIdXmlClassRef();
+ if (idXmlClassRef == null) {
+ return null;
+ }
+
+ String className = idXmlClassRef.getClassName();
+ if (className == null) {
+ return null;
+ }
+
+ return this.getEntityMappings().resolveJavaResourcePersistentType(className);
}
protected EntityMappings getEntityMappings() {
@@ -208,9 +212,10 @@ public class GenericOrmIdClassReference
// **************** validation ********************************************
public TextRange getValidationTextRange() {
- XmlClassReference element = getIdClassElement();
- return (element == null) ?
- getTypeMapping().getValidationTextRange() : element.getClassNameTextRange();
+ XmlClassReference idXmlClassRef = getIdXmlClassRef();
+ return (idXmlClassRef == null) ?
+ this.getTypeMapping().getValidationTextRange() :
+ idXmlClassRef.getClassNameTextRange();
}
@Override
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 12e161aca5..0a593cef94 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,17 +10,22 @@
package org.eclipse.jpt.core.internal.context.persistence;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import java.util.Set;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.core.JpaProject;
import org.eclipse.jpt.core.JpaStructureNode;
import org.eclipse.jpt.core.JptCorePlugin;
import org.eclipse.jpt.core.context.AccessType;
@@ -28,6 +33,7 @@ import org.eclipse.jpt.core.context.Embeddable;
import org.eclipse.jpt.core.context.Entity;
import org.eclipse.jpt.core.context.Generator;
import org.eclipse.jpt.core.context.MappingFilePersistenceUnitDefaults;
+import org.eclipse.jpt.core.context.PersistentAttribute;
import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.context.Query;
import org.eclipse.jpt.core.context.TypeMapping;
@@ -42,13 +48,16 @@ import org.eclipse.jpt.core.context.persistence.PersistenceUnitTransactionType;
import org.eclipse.jpt.core.context.persistence.PersistentTypeContainer;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
import org.eclipse.jpt.core.jpa2.JpaProject2_0;
import org.eclipse.jpt.core.jpa2.context.MappingFilePersistenceUnitDefaults2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceUnit2_0;
import org.eclipse.jpt.core.jpa2.context.persistence.options.SharedCacheMode;
import org.eclipse.jpt.core.jpa2.context.persistence.options.ValidationMode;
import org.eclipse.jpt.core.jpa2.resource.java.JavaResourcePersistentType2_0;
+import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
import org.eclipse.jpt.core.resource.persistence.PersistenceFactory;
import org.eclipse.jpt.core.resource.persistence.XmlJarFileRef;
import org.eclipse.jpt.core.resource.persistence.XmlJavaClassRef;
@@ -56,6 +65,7 @@ import org.eclipse.jpt.core.resource.persistence.XmlMappingFileRef;
import org.eclipse.jpt.core.resource.persistence.XmlPersistenceUnit;
import org.eclipse.jpt.core.resource.persistence.XmlProperties;
import org.eclipse.jpt.core.resource.persistence.XmlProperty;
+import org.eclipse.jpt.core.utility.BodySourceWriter;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.HashBag;
@@ -70,6 +80,7 @@ import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
@@ -1690,7 +1701,7 @@ public abstract class AbstractPersistenceUnit
}
protected Iterable<IFile> getGeneratedMetamodelFiles() {
- return new TransformationIterable<JavaResourcePersistentType2_0, IFile>(this.getGeneratedMetamodelTypes()) {
+ return new TransformationIterable<JavaResourcePersistentType2_0, IFile>(this.getGeneratedMetamodelTopLevelTypes()) {
@Override
protected IFile transform(JavaResourcePersistentType2_0 jrpt) {
return jrpt.getFile();
@@ -1698,26 +1709,97 @@ public abstract class AbstractPersistenceUnit
};
}
- protected Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTypes() {
- return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelTypes();
+ protected Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTopLevelTypes() {
+ return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelTopLevelTypes();
}
/**
- * If we have the same persistent type in multiple locations, the last one
- * we encounter wins (i.e. the classes in the orm.xml take precedence).
+ * Not the prettiest code....
*/
public void synchronizeMetamodel() {
- // gather the persistent unit's types (eliminating duplicates, ignoring case)
- HashMap<String, PersistentType2_0> persistentTypes = new HashMap<String, PersistentType2_0>();
- this.addContainerPersistentTypesTo(this.getJarFileRefs(), persistentTypes);
- this.addPersistentTypesTo(this.getNonNullClassRefPersistentTypes(), persistentTypes);
- this.addContainerPersistentTypesTo(this.getMappingFileRefs(), persistentTypes);
+ // gather up the persistent unit's types, eliminating duplicates;
+ // if we have persistent types with the same name in multiple locations,
+ // the last one we encounter wins (i.e. the classes in the orm.xml take
+ // precedence)
+ HashMap<String, PersistentType2_0> allPersistentTypes = new HashMap<String, PersistentType2_0>();
+ this.addPersistentTypesTo_(this.getJarFileRefs(), allPersistentTypes);
+ this.addPersistentTypesTo(this.getNonNullClassRefPersistentTypes(), allPersistentTypes);
+ this.addPersistentTypesTo_(this.getMappingFileRefs(), allPersistentTypes);
+
+ // build a list of the top-level types and a tree of their associated
+ // member types etc.
+ ArrayList<MetamodelSourceType> topLevelTypes = new ArrayList<MetamodelSourceType>(allPersistentTypes.size());
+ HashMap<String, Collection<MetamodelSourceType>> memberTypeTree = new HashMap<String, Collection<MetamodelSourceType>>();
+ for (PersistentType2_0 type : allPersistentTypes.values()) {
+ String declaringTypeName = type.getDeclaringTypeName();
+ MetamodelSourceType memberType = type;
+ while (true) {
+ if (declaringTypeName == null) {
+ topLevelTypes.add(memberType);
+ break; // stop at the top-level type
+ }
+
+ // associate the member type with its declaring type
+ Collection<MetamodelSourceType> memberTypes = memberTypeTree.get(declaringTypeName);
+ if (memberTypes == null) {
+ memberTypes = new ArrayList<MetamodelSourceType>();
+ memberTypeTree.put(declaringTypeName, memberTypes);
+ }
+ memberTypes.add(memberType);
+
+ // move out to the member type's declaring type
+ String memberTypeName = declaringTypeName;
+ // check for a context persistent type
+ memberType = allPersistentTypes.get(memberTypeName);
+ if (memberType != null) {
+ break; // stop - this will be processed in the outer 'for' loop
+ }
+ // check for a Java resource persistent type
+ JavaResourcePersistentType jrpt = this.getJpaProject().getJavaResourcePersistentType(memberTypeName);
+ if (jrpt != null) {
+ declaringTypeName = jrpt.getDeclaringTypeName();
+ } else {
+ // check for a JDT type
+ IType jdtType = this.findJdtType(memberTypeName);
+ if (jdtType != null) {
+ IType jdtDeclaringType = jdtType.getDeclaringType();
+ declaringTypeName = (jdtDeclaringType == null) ? null : jdtDeclaringType.getFullyQualifiedName('.');
+ } else {
+ // assume we have a non-persistent top-level type...?
+ declaringTypeName = null;
+ }
+ }
+ if (declaringTypeName == null) {
+ memberType = this.selectSourceType(topLevelTypes, memberTypeName);
+ } else {
+ memberType = this.selectSourceType(memberTypeTree.get(declaringTypeName), memberTypeName);
+ }
+ if (memberType != null) {
+ break; // stop - this type has already been processed
+ }
+ memberType = this.buildNonPersistentMetamodelSourceType(memberTypeName);
+ }
+ }
+
+ // remove any top-level type whose name differs from another only by case,
+ // since, on Windows, file names are case-insensitive :-(
+ // sort the original list so we end up with the same top-level type
+ // remaining every time (i.e. the one that sorts out first)
+ Collections.sort(topLevelTypes, MetamodelSourceType.COMPARATOR);
+ HashSet<String> names = new HashSet<String>(topLevelTypes.size());
+ for (Iterator<MetamodelSourceType> stream = topLevelTypes.iterator(); stream.hasNext(); ) {
+ MetamodelSourceType topLevelType = stream.next();
+ // hopefully this is case-insensitive enough...
+ if ( ! names.add(topLevelType.getName().toLowerCase())) {
+ stream.remove();
+ }
+ }
// copy the list of metamodel files...
HashSet<IFile> deadMetamodelFiles = new HashSet<IFile>(this.metamodelFiles);
this.metamodelFiles.clear();
- for (PersistentType2_0 persistentType : persistentTypes.values()) {
- IFile metamodelFile = persistentType.getMetamodelFile();
+ for (MetamodelSourceType topLevelType : topLevelTypes) {
+ IFile metamodelFile = topLevelType.getMetamodelFile();
// ...remove whatever files are still present...
deadMetamodelFiles.remove(metamodelFile);
// ...rebuild the list of metamodel files...
@@ -1732,13 +1814,14 @@ public abstract class AbstractPersistenceUnit
for (IFile deadMetamodelFile : deadMetamodelFiles) {
this.deleteMetamodelFile(deadMetamodelFile);
}
+
// now generate the metamodel classes
- for (PersistentType2_0 persistentType : persistentTypes.values()) {
- persistentType.synchronizeMetamodel();
+ for (MetamodelSourceType topLevelType : topLevelTypes) {
+ topLevelType.synchronizeMetamodel(memberTypeTree);
}
}
- protected void addContainerPersistentTypesTo(Iterable<? extends PersistentTypeContainer> ptContainers, HashMap<String, PersistentType2_0> persistentTypeMap) {
+ protected void addPersistentTypesTo_(Iterable<? extends PersistentTypeContainer> ptContainers, HashMap<String, PersistentType2_0> persistentTypeMap) {
for (PersistentTypeContainer ptContainer : ptContainers) {
this.addPersistentTypesTo(ptContainer.getPersistentTypes(), persistentTypeMap);
}
@@ -1747,10 +1830,33 @@ public abstract class AbstractPersistenceUnit
protected void addPersistentTypesTo(Iterable<? extends PersistentType> persistentTypes, HashMap<String, PersistentType2_0> persistentTypeMap) {
for (PersistentType persistentType : persistentTypes) {
if (persistentType.getName() != null) {
- // hopefully this is case-insensitive enough...
- persistentTypeMap.put(persistentType.getName().toLowerCase(), (PersistentType2_0) persistentType);
+ persistentTypeMap.put(persistentType.getName(), (PersistentType2_0) persistentType);
+ }
+ }
+ }
+
+ protected MetamodelSourceType selectSourceType(Iterable<MetamodelSourceType> types, String typeName) {
+ if (types != null) {
+ for (MetamodelSourceType type : types) {
+ if (type.getName().equals(typeName)) {
+ return type;
+ }
}
}
+ return null;
+ }
+
+ protected MetamodelSourceType buildNonPersistentMetamodelSourceType(String nonPersistentTypeName) {
+ return new NonPersistentMetamodelSourceType(nonPersistentTypeName, this.getJpaProject());
+ }
+
+ protected IType findJdtType(String typeName) {
+ try {
+ return this.getJpaProject().getJavaProject().findType(typeName);
+ } catch (JavaModelException ex) {
+ JptCorePlugin.log(ex);
+ return null;
+ }
}
protected void deleteMetamodelFile(IFile file) {
@@ -1768,11 +1874,67 @@ public abstract class AbstractPersistenceUnit
}
protected boolean fileIsGeneratedMetamodel(IFile file) {
- return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelType(file) != null;
+ return ((JpaProject2_0) this.getJpaProject()).getGeneratedMetamodelTopLevelType(file) != null;
}
public void disposeMetamodel() {
this.metamodelFiles.clear();
}
+ // ***** Metamodel source for non-persistent types
+ protected static class NonPersistentMetamodelSourceType
+ implements MetamodelSourceType
+ {
+ protected final String name;
+ protected final JpaProject jpaProject;
+ protected final MetamodelSourceType.Synchronizer metamodelSynchronizer;
+
+ protected NonPersistentMetamodelSourceType(String name, JpaProject jpaProject) {
+ super();
+ this.name = name;
+ this.jpaProject = jpaProject;
+ this.metamodelSynchronizer = this.buildMetamodelSynchronizer();
+ }
+
+ protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() {
+ return this.getJpaFactory().buildMetamodelSynchronizer(this);
+ }
+
+ protected JpaFactory2_0 getJpaFactory() {
+ return (JpaFactory2_0) this.getJpaProject().getJpaPlatform().getJpaFactory();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public boolean isManaged() {
+ return false;
+ }
+
+ public PersistentType getSuperPersistentType() {
+ return null;
+ }
+
+ public <T extends PersistentAttribute> ListIterator<T> attributes() {
+ return EmptyListIterator.instance();
+ }
+
+ public IFile getMetamodelFile() {
+ return this.metamodelSynchronizer.getFile();
+ }
+
+ public JpaProject getJpaProject() {
+ return this.jpaProject;
+ }
+
+ public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ this.metamodelSynchronizer.synchronize(memberTypeTree);
+ }
+
+ public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree);
+ }
+ }
+
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java
index 9ce20731cd..71b2ad97e5 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java
@@ -15,6 +15,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+import java.util.Map;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
@@ -39,7 +40,8 @@ import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode;
import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
+import org.eclipse.jpt.core.jpa2.context.java.JavaPersistentType2_0;
import org.eclipse.jpt.core.jpa2.context.orm.OrmPersistentType2_0;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
@@ -48,6 +50,7 @@ import org.eclipse.jpt.core.resource.orm.OrmPackage;
import org.eclipse.jpt.core.resource.orm.XmlAttributeMapping;
import org.eclipse.jpt.core.resource.orm.XmlTypeMapping;
import org.eclipse.jpt.core.resource.xml.EmfTools;
+import org.eclipse.jpt.core.utility.BodySourceWriter;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.utility.internal.ClassName;
import org.eclipse.jpt.utility.internal.CollectionTools;
@@ -90,9 +93,11 @@ public class GenericOrmPersistentType
protected PersistentType superPersistentType;
+ protected String declaringTypeName;
+
protected JavaPersistentType javaPersistentType;
- protected final PersistentType2_0.MetamodelSynchronizer metamodelSynchronizer;
+ protected final MetamodelSourceType.Synchronizer metamodelSynchronizer;
public GenericOrmPersistentType(EntityMappings parent, XmlTypeMapping resourceMapping) {
@@ -102,12 +107,15 @@ public class GenericOrmPersistentType
this.defaultAccess = this.buildDefaultAccess();
this.javaPersistentType = this.buildJavaPersistentType();
this.superPersistentType = this.buildSuperPersistentType();
+ this.declaringTypeName = this.buildDeclaringTypeName();
this.initializeAttributes();
this.metamodelSynchronizer = this.buildMetamodelSynchronizer();
}
- protected PersistentType2_0.MetamodelSynchronizer buildMetamodelSynchronizer() {
- return ((JpaFactory2_0) this.getJpaFactory()).buildPersistentTypeMetamodelSynchronizer(this);
+ protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() {
+ return this.isJpa2_0Compatible() ?
+ ((JpaFactory2_0) this.getJpaFactory()).buildMetamodelSynchronizer(this) :
+ null;
}
@@ -119,6 +127,7 @@ public class GenericOrmPersistentType
this.mapping.update();
this.updateJavaPersistentType();
this.updateSuperPersistentType();
+ this.setDeclaringTypeName(this.buildDeclaringTypeName());
this.updateAttributes();
}
@@ -138,8 +147,9 @@ public class GenericOrmPersistentType
// ********** name **********
public String getName() {
- String className = this.mapping.getClass_();
- return className != null ? className.replace('$', '.') : null;
+ String name = this.mapping.getClass_();
+ // nested class names are specified with a '$' in orm.xml
+ return (name == null) ? null : name.replace('$', '.');
}
public String getShortName(){
@@ -687,8 +697,8 @@ public class GenericOrmPersistentType
return this.getEntityMappings().resolveJavaResourcePersistentType(this.getName());
}
- protected JavaResourcePersistentType getJavaResourcePersistentType(String qualifiedClassName) {
- return this.getJpaProject().getJavaResourcePersistentType(qualifiedClassName);
+ protected JavaResourcePersistentType getJavaResourcePersistentType(String className) {
+ return this.getJpaProject().getJavaResourcePersistentType(className);
}
protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) {
@@ -757,6 +767,28 @@ public class GenericOrmPersistentType
}
+ // ********** declaring type name **********
+
+ public String getDeclaringTypeName() {
+ return this.declaringTypeName;
+ }
+
+ protected void setDeclaringTypeName(String declaringTypeName) {
+ String old = this.declaringTypeName;
+ this.declaringTypeName = declaringTypeName;
+ this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, declaringTypeName);
+ }
+
+ protected String buildDeclaringTypeName() {
+ return this.isJpa2_0Compatible() ? buildDeclaringTypeName_() : null;
+ }
+
+ protected String buildDeclaringTypeName_() {
+ return (this.javaPersistentType == null) ?
+ null : ((JavaPersistentType2_0) this.javaPersistentType).getDeclaringTypeName();
+ }
+
+
// ********** metamodel **********
public IFile getMetamodelFile() {
@@ -767,13 +799,23 @@ public class GenericOrmPersistentType
// do nothing - probably shouldn't be called...
}
+ public boolean isManaged() {
+ return true;
+ }
+
/**
* All orm.xml persistent types must be able to generate a static metamodel
* because 1.0 orm.xml files can be referenced from 2.0 persistence.xml files.
*/
- public void synchronizeMetamodel() {
+ public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ if (this.javaPersistentType != null) {
+ this.metamodelSynchronizer.synchronize(memberTypeTree);
+ }
+ }
+
+ public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
if (this.javaPersistentType != null) {
- this.metamodelSynchronizer.synchronize();
+ this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree);
}
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java
index 423301aec9..7b679a02d9 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java
@@ -27,6 +27,7 @@ import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
import org.eclipse.jpt.core.resource.persistence.XmlJavaClassRef;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.Tools;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
@@ -120,7 +121,7 @@ public class GenericClassRef
// ********** queries **********
public boolean isFor(String typeName) {
- return (this.className != null) && this.className.replace('$', '.').equals(typeName);
+ return Tools.valuesAreEqual(typeName, this.getJavaClassName());
}
public boolean isVirtual() {
@@ -155,6 +156,14 @@ public class GenericClassRef
this.firePropertyChanged(CLASS_NAME_PROPERTY, old, newClassName);
}
+ /**
+ * Nested classes will be qualified with a '$'; the Java name is qualified
+ * with a '.'. Like <code>className</code>, this can be <code>null</code>.
+ */
+ protected String getJavaClassName() {
+ return StringTools.stringIsEmpty(this.className) ? null : this.className.replace('$', '.');
+ }
+
// ********** java persistent type **********
@@ -194,7 +203,8 @@ public class GenericClassRef
}
protected JavaResourcePersistentType getJavaResourcePersistentType() {
- return (this.className == null) ? null : this.getJpaProject().getJavaResourcePersistentType(this.className.replace('$', '.'));
+ String javaClassName = this.getJavaClassName();
+ return (javaClassName == null) ? null : this.getJpaProject().getJavaResourcePersistentType(javaClassName);
}
@@ -247,7 +257,7 @@ public class GenericClassRef
DefaultJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
JpaValidationMessages.PERSISTENCE_UNIT_NONEXISTENT_CLASS,
- new String[] {this.className},
+ new String[] {this.getJavaClassName()},
this,
this.getValidationTextRange()
)
@@ -255,16 +265,18 @@ public class GenericClassRef
return;
}
- // 190062 validate Java class only if this is the only reference to it
+ // 190062 validate Java class only if this is the only reference to it;
+ // i.e. the persistence.xml ref is the only ref - none of the mapping
+ // files reference the same class
boolean validateJavaPersistentType = true;
- for (Iterator<MappingFileRef> stream = this.getPersistenceUnit().mappingFileRefsContaining(this.className); stream.hasNext(); ) {
+ for (Iterator<MappingFileRef> stream = this.getPersistenceUnit().mappingFileRefsContaining(this.getJavaClassName()); stream.hasNext(); ) {
validateJavaPersistentType = false;
MappingFileRef mappingFileRef = stream.next();
messages.add(
DefaultJpaValidationMessages.buildMessage(
IMessage.LOW_SEVERITY,
JpaValidationMessages.PERSISTENCE_UNIT_REDUNDANT_CLASS,
- new String[] {this.className, mappingFileRef.getFileName()},
+ new String[] {this.getJavaClassName(), mappingFileRef.getFileName()},
this,
this.getValidationTextRange()
)
@@ -289,7 +301,7 @@ public class GenericClassRef
@Override
public void toString(StringBuilder sb) {
- sb.append(this.className);
+ sb.append(this.getJavaClassName());
}
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
index 3fb05ca72e..32c814c96c 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericJpaFactory2_0.java
@@ -16,6 +16,7 @@ import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.context.java.JavaAssociationOverride;
import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer;
import org.eclipse.jpt.core.context.java.JavaAssociationOverrideRelationshipReference;
+import org.eclipse.jpt.core.context.java.JavaBaseColumn.Owner;
import org.eclipse.jpt.core.context.java.JavaColumn;
import org.eclipse.jpt.core.context.java.JavaEmbeddable;
import org.eclipse.jpt.core.context.java.JavaJpaContextNode;
@@ -27,7 +28,6 @@ import org.eclipse.jpt.core.context.java.JavaOneToOneMapping;
import org.eclipse.jpt.core.context.java.JavaPersistentAttribute;
import org.eclipse.jpt.core.context.java.JavaPersistentType;
import org.eclipse.jpt.core.context.java.JavaSequenceGenerator;
-import org.eclipse.jpt.core.context.java.JavaBaseColumn.Owner;
import org.eclipse.jpt.core.internal.AbstractJpaFactory;
import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaAssociationOverrideContainer;
import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaColumn;
@@ -48,7 +48,7 @@ import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaPersistentType
import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaSequenceGenerator2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.VirtualAssociationOverride2_0Annotation;
import org.eclipse.jpt.core.jpa2.JpaProject2_0;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheable2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheableHolder2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCollectionTable2_0;
@@ -89,8 +89,8 @@ public class GenericJpaFactory2_0
}
@Override
- public PersistentType2_0.MetamodelSynchronizer buildPersistentTypeMetamodelSynchronizer(PersistentType2_0 persistentType) {
- return new GenericPersistentTypeMetamodelSynchronizer(persistentType);
+ public MetamodelSourceType.Synchronizer buildMetamodelSynchronizer(MetamodelSourceType sourceType) {
+ return new GenericMetamodelSynchronizer(sourceType);
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericMetamodelSynchronizer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericMetamodelSynchronizer.java
new file mode 100644
index 0000000000..8dc8d64205
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericMetamodelSynchronizer.java
@@ -0,0 +1,432 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 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.jpa2;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jpt.core.JptCorePlugin;
+import org.eclipse.jpt.core.context.AttributeMapping;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.jpa2.JpaProject2_0;
+import org.eclipse.jpt.core.jpa2.context.AttributeMapping2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelField;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
+import org.eclipse.jpt.core.jpa2.resource.java.JPA2_0;
+import org.eclipse.jpt.core.jpa2.resource.java.JavaResourcePersistentType2_0;
+import org.eclipse.jpt.core.utility.BodySourceWriter;
+import org.eclipse.jpt.utility.internal.ClassName;
+import org.eclipse.jpt.utility.internal.SimpleStack;
+import org.eclipse.jpt.utility.internal.StringTools;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+
+/**
+ * For now, the "synchronization" is simple brute-force: we generate the source
+ * code and then compare it with what is already present in the file.
+ * If the new source is different, we replace the file contents; otherwise, we
+ * leave the file unchanged.
+ */
+@SuppressWarnings("nls")
+public class GenericMetamodelSynchronizer
+ implements MetamodelSourceType.Synchronizer
+{
+ protected final MetamodelSourceType sourceType;
+
+
+ public GenericMetamodelSynchronizer(MetamodelSourceType sourceType) {
+ super();
+ this.sourceType = sourceType;
+ }
+
+ public IFile getFile() {
+ return (IFile) this.getPackageFragment().getCompilationUnit(this.getFileName()).getResource();
+ }
+
+
+ // ********** synchronize **********
+
+ public void synchronize(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ try {
+ this.synchronize_(memberTypeTree);
+ } catch (JavaModelException ex) {
+ JptCorePlugin.log(ex);
+ }
+ }
+
+ protected void synchronize_(Map<String, Collection<MetamodelSourceType>> memberTypeTree) throws JavaModelException {
+ IPackageFragment pkg = this.getPackageFragment();
+ String fileName = this.getFileName();
+
+ ICompilationUnit compilationUnit = pkg.getCompilationUnit(fileName);
+ if (compilationUnit.exists()) {
+ // overwrite existing file if it has changed (ignoring the timestamp)
+ String newSource = this.buildSource(compilationUnit, memberTypeTree);
+ if (newSource != null) {
+ pkg.createCompilationUnit(fileName, newSource, true, null); // true=force
+ }
+ } else {
+ // write a new file, creating the package folders if necessary
+ if ( ! pkg.exists()) {
+ this.getSourceFolder().createPackageFragment(pkg.getElementName(), true, null); // true=force
+ }
+ pkg.createCompilationUnit(fileName, this.buildSource(memberTypeTree), false, null); // false=no force
+ }
+ }
+
+ /**
+ * pre-condition: the compilation unit exists
+ *
+ * return null if the old source is not to be replaced
+ */
+ protected String buildSource(ICompilationUnit compilationUnit, Map<String, Collection<MetamodelSourceType>> memberTypeTree) throws JavaModelException {
+ IFile file = (IFile) compilationUnit.getResource();
+ JavaResourcePersistentType2_0 genType = this.getJpaProject().getGeneratedMetamodelTopLevelType(file);
+ if (genType == null) {
+ return null; // the file exists, but its source is not a generated metamodel top-level class
+ }
+
+ String oldSource = compilationUnit.getSource();
+ int oldLength = oldSource.length();
+
+ String newSource = this.buildSource(memberTypeTree);
+ int newLength = newSource.length();
+ if (newLength != oldLength) {
+ return newSource;
+ }
+
+ String date = genType.getGeneratedAnnotation().getDate(); // if we get here, this will be non-empty
+ int dateBegin = oldSource.indexOf(date);
+ if (dateBegin == -1) {
+ return null; // hmmm...
+ }
+ int dateEnd = dateBegin + date.length();
+ if (dateEnd > oldLength) {
+ return null; // hmmm...
+ }
+
+ if (newSource.regionMatches(0, oldSource, 0, dateBegin) &&
+ newSource.regionMatches(dateEnd, oldSource, dateEnd, oldLength - dateEnd)) {
+ return null;
+ }
+ return newSource;
+ }
+
+
+ // ********** package/file **********
+
+ protected IPackageFragment getPackageFragment() {
+ return this.getSourceFolder().getPackageFragment(this.getPackageName());
+ }
+
+ protected IPackageFragmentRoot getSourceFolder() {
+ return this.getJpaProject().getMetamodelPackageFragmentRoot();
+ }
+
+ protected JpaProject2_0 getJpaProject() {
+ return (JpaProject2_0) this.sourceType.getJpaProject();
+ }
+
+ protected String getPackageName() {
+ return this.buildPackageName(this.sourceType.getName());
+ }
+
+ protected String buildPackageName(String topLevelSourceTypeName) {
+ return this.buildPackageName_(ClassName.getPackageName(topLevelSourceTypeName));
+ }
+
+ // TODO
+ protected String buildPackageName_(String sourcePackageName) {
+ // the default is to store the metamodel class in the same package as the source type
+ return sourcePackageName;
+ }
+
+ protected String getFileName() {
+ return ClassName.getSimpleName(this.getClassName()) + ".java";
+ }
+
+ protected String getClassName() {
+ return this.buildClassName(this.sourceType.getName());
+ }
+
+ protected String buildClassName(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ return this.buildClassName(this.sourceType.getName(), memberTypeTree);
+ }
+
+ protected String buildClassName(String sourceTypeName, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ String current = sourceTypeName;
+ SimpleStack<String> stack = new SimpleStack<String>();
+
+ while (true) {
+ stack.push(ClassName.getSimpleName(current));
+ String declaringTypeName = this.getDeclaringTypeName(current, memberTypeTree);
+ if (declaringTypeName == null) {
+ break;
+ }
+ current = declaringTypeName;
+ }
+
+ StringBuilder sb = new StringBuilder(sourceTypeName.length() + 10);
+ sb.append(this.buildPackageName(current));
+ while ( ! stack.isEmpty()) {
+ sb.append('.');
+ sb.append(this.buildSimpleClassName(stack.pop()));
+ }
+ return sb.toString();
+ }
+
+ protected String buildClassName(String topLevelSourceTypeName) {
+ return this.buildPackageName(topLevelSourceTypeName) + '.' + this.buildSimpleClassName(ClassName.getSimpleName(topLevelSourceTypeName));
+ }
+
+ protected String getSimpleClassName() {
+ return this.buildSimpleClassName(ClassName.getSimpleName(this.sourceType.getName()));
+ }
+
+ // TODO
+ protected String buildSimpleClassName(String simpleSourceTypeName) {
+ // the default is to simply append an underscore to the source type name
+ return simpleSourceTypeName + '_';
+ }
+
+
+ // ********** source code **********
+
+ /**
+ * build the "body" source first; then build the "package" and "imports" source
+ * and concatenate the "body" source to it
+ */
+ protected String buildSource(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ // build the body source first so we can gather up the import statements
+ BodySourceWriter bodySourceWriter = this.buildBodySourceWriter(memberTypeTree);
+
+ StringWriter sw = new StringWriter(bodySourceWriter.getLength() + 2000);
+ PrintWriter pw = new PrintWriter(sw);
+ this.printPackageAndImportsOn(pw, bodySourceWriter);
+ pw.print(bodySourceWriter.getSource());
+ return sw.toString();
+ }
+
+ protected BodySourceWriter buildBodySourceWriter(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ BodySourceWriter pw = new BodySourceWriter(this.getPackageName(), this.getClassName());
+ this.printBodySourceOn(pw, memberTypeTree);
+ return pw;
+ }
+
+ public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ this.printClassDeclarationOn(pw, memberTypeTree);
+ pw.print(" {");
+ pw.println();
+
+ pw.indent();
+ boolean attributesPrinted = this.printAttributesOn(pw);
+ this.printMemberTypesOn(pw, memberTypeTree, attributesPrinted);
+ pw.undent();
+
+ pw.print('}');
+ pw.println(); // EOF
+ }
+
+
+ // ********** class declaration **********
+
+ protected void printClassDeclarationOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ boolean topLevel = this.sourceTypeIsTopLevel(memberTypeTree);
+ if (topLevel) {
+ this.printGeneratedAnnotationOn(pw);
+ }
+ if (this.sourceType.isManaged()) {
+ this.printStaticMetamodelAnnotationOn(pw);
+ }
+
+ pw.print("public ");
+ if ( ! topLevel) {
+ pw.print("static ");
+ }
+ pw.print("class ");
+ pw.print(this.getSimpleClassName()); // this is always the simple name
+ PersistentType superPersistentType = this.sourceType.getSuperPersistentType();
+ if (superPersistentType != null) {
+ pw.print(" extends ");
+ pw.printTypeDeclaration(this.buildClassName(superPersistentType.getName(), memberTypeTree));
+ }
+ }
+
+ /**
+ * Return whether the source type is a top level type.
+ * This can be inferred from the specified member type tree.
+ */
+ protected boolean sourceTypeIsTopLevel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ return this.sourceTypeIsTopLevel(this.sourceType.getName(), memberTypeTree);
+ }
+
+ /**
+ * Return whether the specified source type is a top level type.
+ * This can be inferred from the specified member type tree.
+ */
+ protected boolean sourceTypeIsTopLevel(String sourceTypeName, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ return this.getDeclaringTypeName(sourceTypeName, memberTypeTree) == null;
+ }
+
+ /**
+ * Return the name of the specified source type's declaring type, as
+ * implied by the specified member type tree. Return null if the source
+ * type is a top-level type.
+ */
+ protected String getDeclaringTypeName(String sourceTypeName, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ int lastPeriod = sourceTypeName.lastIndexOf('.');
+ if (lastPeriod == -1) {
+ return null; // default package top-level type
+ }
+ String declaringTypeName = sourceTypeName.substring(0, lastPeriod);
+ return (memberTypeTree.get(declaringTypeName) == null) ? null : declaringTypeName;
+ }
+
+ protected void printGeneratedAnnotationOn(BodySourceWriter pw) {
+ pw.printAnnotation("javax.annotation.Generated");
+ pw.print('(');
+ pw.print("value=");
+ pw.printStringLiteral(JavaResourcePersistentType2_0.METAMODEL_GENERATED_ANNOTATION_VALUE);
+ pw.print(", ");
+ pw.print("date=");
+ pw.printStringLiteral(format(new Date()));
+ pw.print(')');
+ pw.println();
+ }
+
+ protected void printStaticMetamodelAnnotationOn(BodySourceWriter pw) {
+ pw.printAnnotation(JPA2_0.STATIC_METAMODEL);
+ pw.print('(');
+ pw.printTypeDeclaration(this.sourceType.getName());
+ pw.print(".class");
+ pw.print(')');
+ pw.println();
+ }
+
+ /**
+ * {@link SimpleDateFormat} is not thread-safe.
+ */
+ protected static synchronized String format(Date date) {
+ return DATE_FORMAT.format(date);
+ }
+ /**
+ * Recommended date format is ISO 8601.
+ * @see javax.annotation.Generated
+ */
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+
+
+ // ********** attributes **********
+
+ /**
+ * Return whether any attributes were printed.
+ */
+ protected boolean printAttributesOn(BodySourceWriter pw) {
+ boolean printed = false;
+ for (Iterator<PersistentAttribute> stream = this.sourceType.attributes(); stream.hasNext(); ) {
+ this.printAttributeOn(stream.next(), pw);
+ printed = true;
+ }
+ return printed;
+ }
+
+ protected void printAttributeOn(PersistentAttribute persistentAttribute, BodySourceWriter pw) {
+ AttributeMapping attributeMapping = persistentAttribute.getMapping();
+ if (attributeMapping != null) { // probably shouldn't be null?
+ this.printAttributeMappingOn(attributeMapping, pw);
+ }
+ }
+
+ protected void printAttributeMappingOn(AttributeMapping attributeMapping, BodySourceWriter pw) {
+ MetamodelField field = ((AttributeMapping2_0) attributeMapping).getMetamodelField();
+ if (field != null) {
+ this.printFieldOn(field, pw);
+ }
+ }
+
+ protected void printFieldOn(MetamodelField field, BodySourceWriter pw) {
+ for (String modifier : field.getModifiers()) {
+ pw.print(modifier);
+ pw.print(' ');
+ }
+ pw.printTypeDeclaration(field.getTypeName());
+ pw.print('<');
+ for (Iterator<String> stream = field.getTypeArgumentNames().iterator(); stream.hasNext(); ) {
+ pw.printTypeDeclaration(stream.next());
+ if (stream.hasNext()) {
+ pw.print(", ");
+ }
+ }
+ pw.print('>');
+ pw.print(' ');
+ pw.print(field.getName());
+ pw.print(';');
+ pw.println();
+ }
+
+
+ // ********** member types **********
+
+ protected void printMemberTypesOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree, boolean attributesPrinted) {
+ Collection<MetamodelSourceType> memberTypes = memberTypeTree.get(this.sourceType.getName());
+ if (memberTypes != null) {
+ if (attributesPrinted) {
+ pw.println();
+ }
+ for (Iterator<MetamodelSourceType> stream = memberTypes.iterator(); stream.hasNext(); ) {
+ stream.next().printBodySourceOn(pw, memberTypeTree);
+ if (stream.hasNext()) {
+ pw.println();
+ }
+ }
+ }
+ }
+
+
+ // ********** package and imports **********
+
+ protected void printPackageAndImportsOn(PrintWriter pw, BodySourceWriter bodySourceWriter) {
+ if (this.getPackageName().length() != 0) {
+ pw.print("package ");
+ pw.print(this.getPackageName());
+ pw.print(';');
+ pw.println();
+ pw.println();
+ }
+
+ for (String import_ : bodySourceWriter.getImports()) {
+ pw.print("import ");
+ pw.print(import_);
+ pw.print(';');
+ pw.println();
+ }
+ pw.println();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this, this.sourceType.getName());
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java
deleted file mode 100644
index 6e6108c88a..0000000000
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java
+++ /dev/null
@@ -1,604 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009, 2010 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.jpa2;
-
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeSet;
-import java.util.Map.Entry;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jpt.core.JptCorePlugin;
-import org.eclipse.jpt.core.context.AttributeMapping;
-import org.eclipse.jpt.core.context.PersistentAttribute;
-import org.eclipse.jpt.core.context.PersistentType;
-import org.eclipse.jpt.core.jpa2.JpaProject2_0;
-import org.eclipse.jpt.core.jpa2.context.AttributeMapping2_0;
-import org.eclipse.jpt.core.jpa2.context.MetamodelField;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
-import org.eclipse.jpt.core.jpa2.resource.java.JPA2_0;
-import org.eclipse.jpt.core.jpa2.resource.java.JavaResourcePersistentType2_0;
-import org.eclipse.jpt.utility.Filter;
-import org.eclipse.jpt.utility.internal.ClassName;
-import org.eclipse.jpt.utility.internal.CollectionTools;
-import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
-import org.eclipse.jpt.utility.internal.StringTools;
-import org.eclipse.jpt.utility.internal.Transformer;
-import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
-import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
-
-import com.ibm.icu.text.Collator;
-import com.ibm.icu.text.DateFormat;
-import com.ibm.icu.text.SimpleDateFormat;
-
-/**
- * For now, the "synchronization" is simple brute-force: we generate the source
- * code and then compare it with what is already present in the file.
- * If the new source is different, we replace the file contents; otherwise, we
- * leave the file unchanged.
- */
-@SuppressWarnings("nls")
-public class GenericPersistentTypeMetamodelSynchronizer
- implements PersistentType2_0.MetamodelSynchronizer
-{
- protected final PersistentType2_0 persistentType;
-
-
- public GenericPersistentTypeMetamodelSynchronizer(PersistentType2_0 persistentType) {
- super();
- this.persistentType = persistentType;
- }
-
- public IFile getFile() {
- return (IFile) this.getPackageFragment().getCompilationUnit(this.getFileName()).getResource();
- }
-
-
- // ********** synchronize **********
-
- public void synchronize() {
- try {
- this.synchronize_();
- } catch (JavaModelException ex) {
- JptCorePlugin.log(ex);
- }
- }
-
- protected void synchronize_() throws JavaModelException {
- IPackageFragment pkg = this.getPackageFragment();
- String fileName = this.getFileName();
-
- ICompilationUnit compilationUnit = pkg.getCompilationUnit(fileName);
- if (compilationUnit.exists()) {
- // overwrite existing file if it has changed (ignoring the timestamp)
- String newSource = this.buildSource(compilationUnit);
- if (newSource != null) {
- pkg.createCompilationUnit(fileName, newSource, true, null); // true=force
- }
- } else {
- // write a new file, creating the package folders if necessary
- if ( ! pkg.exists()) {
- this.getSourceFolder().createPackageFragment(pkg.getElementName(), true, null); // true=force
- }
- pkg.createCompilationUnit(fileName, this.buildSource(), false, null); // false=no force
- }
- }
-
- /**
- * pre-condition: the compilation unit exists
- *
- * return null if the old source is not to be replaced
- */
- protected String buildSource(ICompilationUnit compilationUnit) throws JavaModelException {
- IFile file = (IFile) compilationUnit.getResource();
- JavaResourcePersistentType2_0 genType = this.getJpaProject().getGeneratedMetamodelType(file);
- if (genType == null) {
- return null; // the file exists, but its source is not a generated metamodel class
- }
-
- String oldSource = compilationUnit.getSource();
- int oldLength = oldSource.length();
-
- String newSource = this.buildSource();
- int newLength = newSource.length();
- if (newLength != oldLength) {
- return newSource;
- }
-
- String date = genType.getGeneratedAnnotation().getDate(); // if we get here, this will be non-empty
- int dateBegin = oldSource.indexOf(date);
- if (dateBegin == -1) {
- return null; // hmmm...
- }
- int dateEnd = dateBegin + date.length();
- if (dateEnd > oldLength) {
- return null; // hmmm...
- }
-
- if (newSource.regionMatches(0, oldSource, 0, dateBegin) &&
- newSource.regionMatches(dateEnd, oldSource, dateEnd, oldLength - dateEnd)) {
- return null;
- }
- return newSource;
- }
-
-
- // ********** package/file **********
-
- protected IPackageFragment getPackageFragment() {
- return this.getSourceFolder().getPackageFragment(this.getPackageName());
- }
-
- protected IPackageFragmentRoot getSourceFolder() {
- return this.getJpaProject().getMetamodelPackageFragmentRoot();
- }
-
- protected JpaProject2_0 getJpaProject() {
- return (JpaProject2_0) this.persistentType.getJpaProject();
- }
-
- // TODO
- protected String getPackageName() {
- // the default is to store the metamodel in the same package as the model
- return ClassName.getPackageName(this.getMetamodelClassName());
- }
-
- protected String getFileName() {
- return ClassName.getSimpleName(this.getMetamodelClassName()) + ".java";
- }
-
- protected String getMetamodelClassName() {
- return this.buildMetamodelClassName(this.persistentType.getName());
- }
-
- // TODO
- protected String buildMetamodelClassName(String className) {
- // the default is to simply append an underscore to the model class name
- return className + '_';
- }
-
-
- // ********** source code **********
-
- /**
- * build the "body" source first; then build the "package" and "imports" source
- * and concatenate the "body" source to it
- */
- protected String buildSource() {
- // build the body source first so we can gather up the import statements
- BodySourceWriter bodySourceWriter = this.buildBodySourceWriter();
-
- StringWriter sw = new StringWriter(bodySourceWriter.getLength() + 2000);
- PrintWriter pw = new PrintWriter(sw);
- this.printPackageAndImportsOn(pw, bodySourceWriter);
- pw.print(bodySourceWriter.getSource());
- return sw.toString();
- }
-
- protected BodySourceWriter buildBodySourceWriter() {
- BodySourceWriter pw = new BodySourceWriter(this.getPackageName(), this.getMetamodelClassName());
- this.printBodySourceOn(pw);
- return pw;
- }
-
- protected void printBodySourceOn(BodySourceWriter pw) {
- this.printClassDeclarationOn(pw);
- pw.print(" {");
- pw.println();
-
- pw.indent();
- this.printAttributesOn(pw);
- pw.undent();
-
- pw.print('}');
- pw.println(); // EOF
- }
-
-
- // ********** class declaration **********
-
- protected void printClassDeclarationOn(BodySourceWriter pw) {
- this.printGeneratedAnnotationOn(pw);
- this.printStaticMetamodelAnnotationOn(pw);
-
- pw.print("public class ");
- pw.printTypeDeclaration(this.getMetamodelClassName());
- PersistentType superPersistentType = this.persistentType.getSuperPersistentType();
- if (superPersistentType != null) {
- pw.print(" extends ");
- pw.printTypeDeclaration(this.buildMetamodelClassName(superPersistentType.getName()));
- }
- }
-
- protected void printStaticMetamodelAnnotationOn(BodySourceWriter pw) {
- pw.printAnnotation(JPA2_0.STATIC_METAMODEL);
- pw.print('(');
- pw.printTypeDeclaration(this.persistentType.getName());
- pw.print(".class");
- pw.print(')');
- pw.println();
- }
-
- protected void printGeneratedAnnotationOn(BodySourceWriter pw) {
- pw.printAnnotation("javax.annotation.Generated");
- pw.print('(');
- pw.print("value=");
- pw.printStringLiteral(JavaResourcePersistentType2_0.METAMODEL_GENERATED_ANNOTATION_VALUE);
- pw.print(", ");
- pw.print("date=");
- pw.printStringLiteral(format(new Date()));
- pw.print(')');
- pw.println();
- }
-
- /**
- * {@link SimpleDateFormat} is not thread-safe.
- */
- protected static synchronized String format(Date date) {
- return DATE_FORMAT.format(date);
- }
- /**
- * Recommended date format is ISO 8601.
- * @see javax.annotation.Generated
- */
- private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
-
- // ********** attributes **********
-
- protected void printAttributesOn(BodySourceWriter pw) {
- for (Iterator<PersistentAttribute> stream = this.persistentType.attributes(); stream.hasNext(); ) {
- this.printAttributeOn(stream.next(), pw);
- }
- }
-
- protected void printAttributeOn(PersistentAttribute persistentAttribute, BodySourceWriter pw) {
- AttributeMapping attributeMapping = persistentAttribute.getMapping();
- if (attributeMapping != null) { // probably shouldn't be null?
- this.printAttributeMappingOn(attributeMapping, pw);
- }
- }
-
- protected void printAttributeMappingOn(AttributeMapping attributeMapping, BodySourceWriter pw) {
- MetamodelField field = ((AttributeMapping2_0) attributeMapping).getMetamodelField();
- if (field != null) {
- this.printFieldOn(field, pw);
- }
- }
-
- protected void printFieldOn(MetamodelField field, BodySourceWriter pw) {
- for (String modifier : field.getModifiers()) {
- pw.print(modifier);
- pw.print(' ');
- }
- pw.printTypeDeclaration(field.getTypeName());
- pw.print('<');
- for (Iterator<String> stream = field.getTypeArgumentNames().iterator(); stream.hasNext(); ) {
- pw.printTypeDeclaration(stream.next());
- if (stream.hasNext()) {
- pw.print(", ");
- }
- }
- pw.print('>');
- pw.print(' ');
- pw.print(field.getName());
- pw.print(';');
- pw.println();
- }
-
-
- // ********** package and imports **********
-
- protected void printPackageAndImportsOn(PrintWriter pw, BodySourceWriter bodySourceWriter) {
- if (this.getPackageName().length() != 0) {
- pw.print("package ");
- pw.print(this.getPackageName());
- pw.print(';');
- pw.println();
- pw.println();
- }
-
- for (String import_ : bodySourceWriter.getImports()) {
- pw.print("import ");
- pw.print(import_);
- pw.print(';');
- pw.println();
- }
- pw.println();
- }
-
-
- // ********** source writer **********
-
- /**
- * Extend IndentingPrintWriter with some methods that facilitate building
- * class source code.
- */
- protected static class BodySourceWriter
- extends IndentingPrintWriter
- {
- protected final String packageName;
- protected final String className;
- // key = short class name; value = import package
- protected final HashMap<String, ImportPackage> imports = new HashMap<String, ImportPackage>();
-
- protected BodySourceWriter(String packageName, String className) {
- super(new StringWriter(2000));
- this.packageName = packageName;
- this.className = className;
- }
-
- protected String getSource() {
- return this.out.toString();
- }
-
- protected int getLength() {
- return ((StringWriter) this.out).getBuffer().length();
- }
-
- protected void printVisibility(String visibilityModifier) {
- if (visibilityModifier.length() != 0) {
- this.print(visibilityModifier);
- this.print(' ');
- }
- }
-
- protected void printAnnotation(String annotationName) {
- this.print('@');
- this.printTypeDeclaration(annotationName);
- }
-
- protected void printTypeDeclaration(String typeDeclaration) {
- this.print(this.buildImportedTypeDeclaration(typeDeclaration));
- }
-
- protected void printField(String fieldName, String typeDeclaration, String visibility) {
- this.printVisibility(visibility);
- this.printTypeDeclaration(typeDeclaration);
- this.print(' ');
- this.print(fieldName);
- this.print(';');
- this.println();
- this.println();
- }
-
- protected void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) {
- this.printVisibility(visibility);
- this.printTypeDeclaration(typeDeclaration);
- this.print('<');
- this.printTypeDeclaration(parameterTypeDeclaration);
- this.print('>');
- this.print(' ');
- this.print(fieldName);
- this.print(';');
- this.println();
- this.println();
- }
-
- /**
- * Convert the specified string to a String Literal and print it,
- * adding the surrounding double-quotes and escaping characters
- * as necessary.
- */
- void printStringLiteral(String string) {
- StringTools.convertToJavaStringLiteralOn(string, this);
- }
-
-
- // ********** imports **********
-
- // ***** writing
- /**
- * Return the specified class's "imported" name.
- * The class declaration must be of the form:
- * "int"
- * "int[]" (not "[I")
- * "java.lang.Object"
- * "java.lang.Object[]" (not "[Ljava.lang.Object;")
- * "java.util.Map.Entry" (not "java.util.Map$Entry")
- * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
- *
- * To really do this right, we would need to gather all the types from
- * the "unamed" (default) package that were referenced in the
- * compilation unit beforehand. *Any* collisions with one of these
- * types would have to be fully qualified (whether it was from
- * 'java.lang' or the same package as the current compilation unit).
- * In other words, if we have any types from the "unnamed" package,
- * results are unpredictable....
- */
- protected String buildImportedTypeDeclaration(String typeDeclaration) {
- if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
- // no need for an import, just return the partially-qualified name
- return this.buildMemberClassTypeDeclaration(typeDeclaration);
- }
- int last = typeDeclaration.lastIndexOf('.');
- String currentPackageName = (last == -1) ? "" : typeDeclaration.substring(0, last);
- String shortTypeDeclaration = typeDeclaration.substring(last + 1);
- String shortElementTypeName = shortTypeDeclaration;
- while (shortElementTypeName.endsWith("[]")) {
- shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
- }
- ImportPackage prev = this.imports.get(shortElementTypeName);
- if (prev == null) {
- // this is the first class with this short element type name
- this.imports.put(shortElementTypeName, new ImportPackage(currentPackageName));
- return shortTypeDeclaration;
- }
- if (prev.packageName.equals(currentPackageName)) {
- // this element type has already been imported
- return shortTypeDeclaration;
- }
- if (currentPackageName.equals(this.packageName) &&
- prev.packageName.equals("java.lang")) {
- // we force the 'java.lang' class to be explicitly imported
- prev.collision = true;
- }
- // another class with the same short element type name has been
- // previously imported, so this one must be used fully-qualified
- return typeDeclaration;
- }
-
- /**
- * e.g. "foo.bar.Employee.PK" will return true
- */
- protected boolean typeDeclarationIsMemberClass(String typeDeclaration) {
- return (typeDeclaration.length() > this.className.length())
- && typeDeclaration.startsWith(this.className)
- && (typeDeclaration.charAt(this.className.length()) == '.');
- }
-
- /**
- * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
- * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
- */
- protected String buildMemberClassTypeDeclaration(String typeDeclaration) {
- int index = this.packageName.length();
- if (index != 0) {
- index++; // bump past the '.'
- }
- return typeDeclaration.substring(index);
- }
-
- // ***** reading
- protected Iterable<String> getImports() {
- return this.getSortedRequiredImports();
- }
-
- /**
- * transform our map entries to class names
- */
- protected Iterable<String> getSortedRequiredImports() {
- return new TransformationIterable<Map.Entry<String, ImportPackage>, String>(this.getSortedRequiredImportEntries(), this.buildImportEntriesTransformer());
- }
-
- protected Transformer<Map.Entry<String, ImportPackage>, String> buildImportEntriesTransformer() {
- return IMPORT_ENTRIES_TRANSFORMER;
- }
-
- protected static final Transformer<Map.Entry<String, ImportPackage>, String> IMPORT_ENTRIES_TRANSFORMER = new ImportEntriesTransformer();
-
- protected static class ImportEntriesTransformer
- implements Transformer<Map.Entry<String, ImportPackage>, String>
- {
- public String transform(Entry<String, ImportPackage> importEntry) {
- String pkg = importEntry.getValue().packageName;
- String type = importEntry.getKey();
- StringBuilder sb = new StringBuilder(pkg.length() + 1 + type.length());
- sb.append(pkg);
- sb.append('.');
- sb.append(type);
- return sb.toString();
- }
- }
-
- /**
- * sort by package first, then class (*not* by fully-qualified class name)
- */
- protected Iterable<Map.Entry<String, ImportPackage>> getSortedRequiredImportEntries() {
- TreeSet<Map.Entry<String, ImportPackage>> sortedEntries = new TreeSet<Map.Entry<String, ImportPackage>>(this.buildImportEntriesComparator());
- CollectionTools.addAll(sortedEntries, this.getRequiredImportEntries());
- return sortedEntries;
- }
-
- protected Comparator<Map.Entry<String, ImportPackage>> buildImportEntriesComparator() {
- return IMPORT_ENTRIES_COMPARATOR;
- }
-
- protected static final Comparator<Map.Entry<String, ImportPackage>> IMPORT_ENTRIES_COMPARATOR = new ImportEntriesComparator();
-
- protected static class ImportEntriesComparator
- implements Comparator<Map.Entry<String, ImportPackage>>, Serializable
- {
- public int compare(Map.Entry<String, ImportPackage> e1, Map.Entry<String, ImportPackage> e2) {
- Collator collator = Collator.getInstance();
- int pkg = collator.compare(e1.getValue().packageName, e2.getValue().packageName);
- return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
- }
- }
-
- /**
- * strip off any non-required imports (e.g. "java.lang.Object')
- */
- protected Iterable<Map.Entry<String, ImportPackage>> getRequiredImportEntries() {
- return new FilteringIterable<Map.Entry<String, ImportPackage>>(this.imports.entrySet(), this.buildRequiredImportEntriesFilter());
- }
-
- protected Filter<Map.Entry<String, ImportPackage>> buildRequiredImportEntriesFilter() {
- return new RequiredImportEntriesFilter();
- }
-
- protected class RequiredImportEntriesFilter
- implements Filter<Map.Entry<String, ImportPackage>>
- {
- public boolean accept(Map.Entry<String, ImportPackage> importEntry) {
- return this.packageMustBeImported(importEntry.getValue());
- }
-
- protected boolean packageMustBeImported(ImportPackage importPackage) {
- String pkg = importPackage.packageName;
- if (pkg.equals("")) {
- // cannot import a type from the "unnamed" package
- return false;
- }
- if (pkg.equals("java.lang")) {
- // we must import from 'java.lang' if we also have a class in the same package
- return importPackage.collision;
- }
- if (pkg.equals(BodySourceWriter.this.packageName)) {
- // we never need to import a class from the same package
- return false;
- }
- return true;
- }
- }
-
- /**
- * We need a 'collision' flag for when we encounter a class from
- * 'java.lang' followed by a class from the current compilation unit's
- * package. We will need to include the explicit import of the
- * 'java.lang' class and all the references to the other class will
- * have to be fully-qualified.
- *
- * If the classes are encountered in the opposite order (i.e. the class
- * from the current compilation unit's package followed by the class
- * from 'java.lang'), we do *not* need to import the first class while
- * all the references to the 'java.lang' class will be fully-qualified.
- *
- * Unfortunately, we still have a problem: if we reference a class from
- * 'java.lang' and there is a conflicting class from the current
- * compilation unit's package (but that class is *not* revealed to us
- * here), the simple name will be resolved to the non-'java.lang' class.
- * Unless we simply force an import of *all* 'java.lang' classes.... :-(
- *
- * This shouldn't happen very often. :-)
- */
- protected static class ImportPackage {
- protected final String packageName;
- protected boolean collision = false;
-
- protected ImportPackage(String packageName) {
- super();
- this.packageName = packageName;
- }
- }
-
- }
-
-}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaPersistentType2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaPersistentType2_0.java
index 62848905c9..46939ff675 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaPersistentType2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/context/java/GenericJavaPersistentType2_0.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Oracle. All rights reserved.
+ * Copyright (c) 2009, 2010 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.
@@ -9,18 +9,21 @@
******************************************************************************/
package org.eclipse.jpt.core.internal.jpa2.context.java;
+import java.util.Collection;
import java.util.Iterator;
+import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.jpt.core.context.AccessType;
import org.eclipse.jpt.core.context.PersistentType;
import org.eclipse.jpt.core.internal.context.java.AbstractJavaPersistentType;
import org.eclipse.jpt.core.jpa2.JpaFactory2_0;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.java.JavaPersistentType2_0;
import org.eclipse.jpt.core.jpa2.resource.java.Access2_0Annotation;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType;
+import org.eclipse.jpt.core.utility.BodySourceWriter;
/**
* JPA 2.0 Java persistent type.
@@ -30,15 +33,30 @@ public class GenericJavaPersistentType2_0
extends AbstractJavaPersistentType
implements JavaPersistentType2_0
{
- protected final PersistentType2_0.MetamodelSynchronizer metamodelSynchronizer;
+ protected String declaringTypeName;
+
+ protected final MetamodelSourceType.Synchronizer metamodelSynchronizer;
+
public GenericJavaPersistentType2_0(PersistentType.Owner parent, JavaResourcePersistentType jrpt) {
super(parent, jrpt);
this.metamodelSynchronizer = this.buildMetamodelSynchronizer();
}
- protected PersistentType2_0.MetamodelSynchronizer buildMetamodelSynchronizer() {
- return ((JpaFactory2_0) this.getJpaFactory()).buildPersistentTypeMetamodelSynchronizer(this);
+ @Override
+ protected void initialize(JavaResourcePersistentType jrpt) {
+ super.initialize(jrpt);
+ this.declaringTypeName = this.buildDeclaringTypeName();
+ }
+
+ protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() {
+ return ((JpaFactory2_0) this.getJpaFactory()).buildMetamodelSynchronizer(this);
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDeclaringTypeName(this.buildDeclaringTypeName());
}
@@ -84,6 +102,23 @@ public class GenericJavaPersistentType2_0
}
+ // ********** declaring type name **********
+
+ public String getDeclaringTypeName() {
+ return this.declaringTypeName;
+ }
+
+ protected void setDeclaringTypeName(String declaringTypeName) {
+ String old = this.declaringTypeName;
+ this.declaringTypeName = declaringTypeName;
+ this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, declaringTypeName);
+ }
+
+ protected String buildDeclaringTypeName() {
+ return this.resourcePersistentType.getDeclaringTypeName();
+ }
+
+
// ********** metamodel **********
public IFile getMetamodelFile() {
@@ -94,10 +129,18 @@ public class GenericJavaPersistentType2_0
// do nothing - probably shouldn't be called...
}
- public void synchronizeMetamodel() {
- this.metamodelSynchronizer.synchronize();
+ public boolean isManaged() {
+ return true;
+ }
+
+ public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ this.metamodelSynchronizer.synchronize(memberTypeTree);
}
+ public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) {
+ this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree);
+ }
+
public void disposeMetamodel() {
// do nothing - probably shouldn't be called...
}
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 cc21a6e52e..887d519751 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
@@ -48,6 +48,8 @@ final class BinaryPersistentType
private String superclassQualifiedName;
+ private String declaringTypeName;
+
private boolean abstract_; // 'abstract' is a reserved word
private final Vector<JavaResourcePersistentAttribute> fields;
@@ -64,6 +66,7 @@ final class BinaryPersistentType
this.name = this.buildName();
this.qualifiedName = this.buildQualifiedName();
this.superclassQualifiedName = this.buildSuperclassQualifiedName();
+ this.declaringTypeName = this.buildDeclaringTypeName();
this.abstract_ = this.buildAbstract();
this.fields = this.buildFields();
this.methods = this.buildMethods();
@@ -80,6 +83,7 @@ final class BinaryPersistentType
this.setName(this.buildName());
this.setQualifiedName(this.buildQualifiedName());
this.setSuperclassQualifiedName(this.buildSuperclassQualifiedName());
+ this.setDeclaringTypeName(this.buildDeclaringTypeName());
this.setAbstract(this.buildAbstract());
this.updateFields();
this.updateMethods();
@@ -177,6 +181,22 @@ final class BinaryPersistentType
}
}
+ // ***** declaring type name
+ public String getDeclaringTypeName() {
+ return this.declaringTypeName;
+ }
+
+ private void setDeclaringTypeName(String declaringTypeName) {
+ String old = this.declaringTypeName;
+ this.declaringTypeName = declaringTypeName;
+ this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, declaringTypeName);
+ }
+
+ private String buildDeclaringTypeName() {
+ IType declaringType = this.getMember().getDeclaringType();
+ return (declaringType == null) ? null : declaringType.getFullyQualifiedName('.'); // no parameters are included here
+ }
+
// ***** abstract
public boolean isAbstract() {
return this.abstract_;
@@ -544,11 +564,15 @@ final class BinaryPersistentType
throw new UnsupportedOperationException();
}
- public boolean isGeneratedMetamodel(IPackageFragmentRoot sourceFolder) {
+ public boolean isGeneratedMetamodelTopLevelType(IPackageFragmentRoot sourceFolder) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isGeneratedMetamodelTopLevelType() {
throw new UnsupportedOperationException();
}
- public boolean isGeneratedMetamodel() {
+ public boolean isMetamodel() {
throw new UnsupportedOperationException();
}
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 87ac15f5e0..114613bdfd 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
@@ -40,11 +40,11 @@ import org.eclipse.jpt.utility.internal.iterators.SingleElementIterator;
/**
* Java source persistent member (annotations, "persistable")
*/
-abstract class SourcePersistentMember<E extends Member>
+abstract class SourcePersistentMember<M extends Member>
extends SourceNode
implements JavaResourcePersistentMember
{
- final E member;
+ final M member;
/**
* annotations; no duplicates (java compiler has an error for duplicates)
@@ -56,7 +56,7 @@ abstract class SourcePersistentMember<E extends Member>
// ********** construction/initialization **********
- SourcePersistentMember(JavaResourceNode parent, E member) {
+ SourcePersistentMember(JavaResourceNode parent, M member) {
super(parent);
this.member = member;
}
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 219e12a1de..bb20e9b7c6 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
@@ -62,6 +62,8 @@ final class SourcePersistentType
private String superclassQualifiedName;
+ private String declaringTypeName;
+
private boolean abstract_; // 'abstract' is a reserved word
private final Vector<JavaResourcePersistentType> types;
@@ -134,6 +136,7 @@ final class SourcePersistentType
this.name = this.buildName(astRoot);
this.qualifiedName = this.buildQualifiedName(astRoot);
this.superclassQualifiedName = this.buildSuperclassQualifiedName(astRoot);
+ this.declaringTypeName = this.buildDeclaringTypeName(astRoot);
this.abstract_ = this.buildAbstract(astRoot);
this.initializeTypes(astRoot);
this.initializeFields(astRoot);
@@ -173,6 +176,7 @@ final class SourcePersistentType
this.syncName(this.buildName(astRoot));
this.syncQualifiedName(this.buildQualifiedName(astRoot));
this.syncSuperclassQualifiedName(this.buildSuperclassQualifiedName(astRoot));
+ this.syncDeclaringTypeName(this.buildDeclaringTypeName(astRoot));
this.syncAbstract(this.buildAbstract(astRoot));
this.syncTypes(astRoot);
this.syncFields(astRoot);
@@ -309,6 +313,27 @@ final class SourcePersistentType
return (superclass == null) ? null : superclass.getTypeDeclaration().getQualifiedName();
}
+ // ***** declaring type name
+ public String getDeclaringTypeName() {
+ return this.declaringTypeName;
+ }
+
+ private void syncDeclaringTypeName(String astDeclaringTypeName) {
+ String old = this.declaringTypeName;
+ this.declaringTypeName = astDeclaringTypeName;
+ this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, astDeclaringTypeName);
+ }
+
+ private String buildDeclaringTypeName(CompilationUnit astRoot) {
+ ITypeBinding binding = this.member.getBinding(astRoot);
+ if (binding == null) {
+ return null;
+ }
+ ITypeBinding declaringClass = binding.getDeclaringClass();
+ return (declaringClass == null) ? null : declaringClass.getTypeDeclaration().getQualifiedName();
+ }
+
+
// ***** abstract
public boolean isAbstract() {
return this.abstract_;
@@ -654,29 +679,50 @@ final class SourcePersistentType
/**
* The type must be:<ul>
* <li>in the specified source folder
- * <li>annotated with <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
- * <li>annotated with <code>&#64;javax.annotation.Generated</code> with the appropriate
- * <code>value</code>
+ * <li>a top-level type
+ * <li>annotated with <code>&#64;javax.annotation.Generated</code> with
+ * the appropriate <code>value</code> and <code>date</code>
+ * <li>either itself or one of its nested types annotated with
+ * <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
* </ul>
*/
- public boolean isGeneratedMetamodel(IPackageFragmentRoot sourceFolder) {
+ public boolean isGeneratedMetamodelTopLevelType(IPackageFragmentRoot sourceFolder) {
if ( ! this.getSourceFolder().equals(sourceFolder)) {
return false;
}
- return this.isGeneratedMetamodel();
+ return this.isGeneratedMetamodelTopLevelType();
}
/**
* The type must be:<ul>
- * <li>annotated with <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
- * <li>annotated with <code>&#64;javax.annotation.Generated</code> with the appropriate
- * <code>value</code> and <code>date</code>
+ * <li>a top-level type
+ * <li>annotated with <code>&#64;javax.annotation.Generated</code> with
+ * the appropriate <code>value</code> and <code>date</code>
+ * <li>either itself or one of its nested types annotated with
+ * <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>
* </ul>
*/
- public boolean isGeneratedMetamodel() {
- if (this.staticMetamodelAnnotation == null) {
+ public boolean isGeneratedMetamodelTopLevelType() {
+ if ( ! this.isGenerated()) {
return false;
}
+ // if we get here we know we have a top-level type, since only top-level
+ // types are annotated @Generated; now see if anything is a metamodel
+ for (Iterator<JavaResourcePersistentType> stream = this.allTypes(); stream.hasNext(); ) {
+ JavaResourcePersistentType2_0 type = (JavaResourcePersistentType2_0) stream.next();
+ if (type.isMetamodel()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * The type must be annotated with
+ * <code>&#64;javax.annotation.Generated</code> with the appropriate
+ * <code>value</code> and <code>date</code>.
+ */
+ protected boolean isGenerated() {
if (this.generatedAnnotation == null) {
return false;
}
@@ -692,6 +738,14 @@ final class SourcePersistentType
return true;
}
+ /**
+ * The type must be annotated with
+ * <code>&#64;javax.persistence.metamodel.StaticMetamodel</code>.
+ */
+ public boolean isMetamodel() {
+ return this.staticMetamodelAnnotation != null;
+ }
+
private IPackageFragmentRoot getSourceFolder() {
return (IPackageFragmentRoot) this.getJavaResourceCompilationUnit().getCompilationUnit().getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTType.java
index 26de333d42..f3438cfe8f 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTType.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/jdt/JDTType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2005, 2010 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.
@@ -98,10 +98,12 @@ public class JDTType
*/
public TypeDeclaration getBodyDeclaration(CompilationUnit astRoot) {
Type declaringType = this.getDeclaringType();
- return (declaringType == null) ?
- this.getTopLevelTypeDeclaration(astRoot)
- :
- this.getNestedTypeDeclaration(declaringType.getBodyDeclaration(astRoot));
+ if (declaringType == null) {
+ return this.getTopLevelTypeDeclaration(astRoot);
+ }
+ TypeDeclaration typeDeclaration = declaringType.getBodyDeclaration(astRoot);
+ // the type declaration can be null when the source is completely hosed
+ return (typeDeclaration == null) ? null : this.getNestedTypeDeclaration(typeDeclaration);
}
public boolean isPersistable(CompilationUnit astRoot) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
index 655659e95f..57bdc33923 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaFactory2_0.java
@@ -19,7 +19,7 @@ import org.eclipse.jpt.core.context.java.JavaColumn;
import org.eclipse.jpt.core.context.java.JavaJpaContextNode;
import org.eclipse.jpt.core.context.java.JavaNamedColumn;
import org.eclipse.jpt.core.context.java.JavaPersistentAttribute;
-import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheable2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheableHolder2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCollectionTable2_0;
@@ -60,7 +60,7 @@ public interface JpaFactory2_0
*/
DatabaseIdentifierAdapter buildDatabaseIdentifierAdapter(JpaDataSource dataSource);
- PersistentType2_0.MetamodelSynchronizer buildPersistentTypeMetamodelSynchronizer(PersistentType2_0 persistentType);
+ MetamodelSourceType.Synchronizer buildMetamodelSynchronizer(MetamodelSourceType sourceType);
// ********** Java Context Model **********
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaProject2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaProject2_0.java
index a8a137c4ff..8137241489 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaProject2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/JpaProject2_0.java
@@ -64,23 +64,23 @@ public interface JpaProject2_0
/**
* Return the JPA project's generated metamodel Java resource persistent
- * types.
+ * top-level types.
* @see org.eclipse.jpt.core.internal.resource.java.source.SourcePersistentType#isGeneratedMetamodel(IPackageFragmentRoot)
*/
- Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTypes();
+ Iterable<JavaResourcePersistentType2_0> getGeneratedMetamodelTopLevelTypes();
/**
- * Return the generated metamodel Java resource persistent type in the
- * specified file. Return null if any of the following is true:<ul>
+ * Return the top-level generated metamodel Java resource persistent type
+ * in the specified file. Return null if any of the following is true:<ul>
* <li>the file is not a Java source file
- * <li>the file does not contain the source for one and only one Java class
- * <li>the Java class is not annotated with the appropriate
- * <code>javax.persistence.metamodel.StaticMetamodel</code> annotation
- * <li>the Java class is not annotated with the appropriate
+ * <li>the top-level Java class is not annotated with the appropriate
* <code>javax.annotation.Generated</code> annotation
+ * <li>neither the top-level Java class nor any of its nested classes
+ * is annotated with the appropriate
+ * <code>javax.persistence.metamodel.StaticMetamodel</code> annotation
* <ul>
*/
- JavaResourcePersistentType2_0 getGeneratedMetamodelType(IFile file);
+ JavaResourcePersistentType2_0 getGeneratedMetamodelTopLevelType(IFile file);
// ********** construction config **********
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/MetamodelSourceType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/MetamodelSourceType.java
new file mode 100644
index 0000000000..f94469bec2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/MetamodelSourceType.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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.jpa2.context;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jpt.core.JpaProject;
+import org.eclipse.jpt.core.context.PersistentAttribute;
+import org.eclipse.jpt.core.context.PersistentType;
+import org.eclipse.jpt.core.utility.BodySourceWriter;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * JPA 2.0 metamodel source type.
+ * <p>
+ * 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.
+ *
+ * @version 2.3
+ * @since 2.3
+ */
+public interface MetamodelSourceType {
+
+ /**
+ * Return the source type's name.
+ */
+ String getName();
+
+ /**
+ * Return whether the source type is "managed" (i.e. persistent).
+ */
+ boolean isManaged();
+
+ /**
+ * Return the source type's super type.
+ */
+ PersistentType getSuperPersistentType();
+
+ /**
+ * Return the source type's attributes.
+ */
+ <T extends PersistentAttribute> ListIterator<T> attributes();
+
+ /**
+ * Return the file generated as a result of the metamodel synchronization.
+ */
+ IFile getMetamodelFile();
+
+ /**
+ * Return the source type's JPA project.
+ */
+ JpaProject getJpaProject();
+
+ /**
+ * Synchronize the source type's metamodel, using the specified member type
+ * tree.
+ */
+ void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree);
+
+ /**
+ * Print the body of the source type's metamodel class on the specified
+ * writer, using the specified member type tree.
+ */
+ void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree);
+
+
+ /**
+ * {@link Comparator} that can be used to compare source types.
+ */
+ Comparator<MetamodelSourceType> COMPARATOR =
+ new Comparator<MetamodelSourceType>() {
+ public int compare(MetamodelSourceType type1, MetamodelSourceType type2) {
+ return Collator.getInstance().compare(type1.getName(), type2.getName());
+ }
+ };
+
+
+ /**
+ * This interface is used by the source type to synchronize the metamodel
+ * as required by changes to the context model.
+ */
+ interface Synchronizer {
+ /**
+ * Return the file generated as a result of the metamodel synchronization.
+ */
+ IFile getFile();
+
+ /**
+ * Synchronize the metamodel with the current state of the source
+ * type, using the specified member type tree.
+ */
+ void synchronize(Map<String, Collection<MetamodelSourceType>> memberTypeTree);
+
+ /**
+ * Print the body of the metamodel class on the specified writer,
+ * using the specified member type tree.
+ */
+ void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree);
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/PersistentType2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/PersistentType2_0.java
index f8df1e5988..6170a1bc7d 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/PersistentType2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/context/PersistentType2_0.java
@@ -9,9 +9,7 @@
******************************************************************************/
package org.eclipse.jpt.core.jpa2.context;
-import org.eclipse.core.resources.IFile;
import org.eclipse.jpt.core.context.PersistentType;
-import org.eclipse.jpt.core.jpa2.MetamodelSynchronizer;
/**
* JPA 2.0 context persistent type.
@@ -26,28 +24,14 @@ import org.eclipse.jpt.core.jpa2.MetamodelSynchronizer;
* @since 2.3
*/
public interface PersistentType2_0
- extends PersistentType, MetamodelSynchronizer
+ extends PersistentType, MetamodelSourceType
{
/**
- * Return the file generated as a result of the metamodel synchronization.
+ * Return the name of the persistent type's "declaring type".
+ * Return <code>null</code> if the persistent type is a top-level type.
+ * The declaring type may or may not be a persistent type.
*/
- IFile getMetamodelFile();
-
- /**
- * This interface is used by the persistent type to synchonize the metamodel
- * as required by changes to the context model.
- */
- interface MetamodelSynchronizer {
- /**
- * Return the file generated as a result of the metamodel synchronization.
- */
- IFile getFile();
-
- /**
- * Synchronize the metamodel with the current state of the persistent
- * type.
- */
- void synchronize();
- }
+ String getDeclaringTypeName();
+ String DECLARING_TYPE_NAME_PROPERTY = "declaringTypeName"; //$NON-NLS-1$
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/resource/java/JavaResourcePersistentType2_0.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/resource/java/JavaResourcePersistentType2_0.java
index f463f335b6..b00ba0b4c8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/resource/java/JavaResourcePersistentType2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/jpa2/resource/java/JavaResourcePersistentType2_0.java
@@ -36,15 +36,22 @@ public interface JavaResourcePersistentType2_0
GeneratedAnnotation getGeneratedAnnotation();
/**
- * Return whether the type is a metamodel type generated in the specified
- * source folder.
+ * Return whether the type is a metamodel top-level type generated in the
+ * specified source folder.
*/
- boolean isGeneratedMetamodel(IPackageFragmentRoot sourceFolder);
+ boolean isGeneratedMetamodelTopLevelType(IPackageFragmentRoot sourceFolder);
/**
- * Return whether the type is a generated metamodel type.
+ * Return whether the type is a generated metamodel top-level type.
+ * The type is generated and either it or one of its nested types is a
+ * metamodel type.
*/
- boolean isGeneratedMetamodel();
+ boolean isGeneratedMetamodelTopLevelType();
+
+ /**
+ * Return whether the type is a metamodel type.
+ */
+ boolean isMetamodel();
/**
* The value used to tag a generated type:
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 31ebf6b6a0..14db8475e3 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
@@ -45,6 +45,13 @@ public interface JavaResourcePersistentType
String SUPERCLASS_QUALIFIED_NAME_PROPERTY = "superclassQualifiedName"; //$NON-NLS-1$
/**
+ * Return the name of the type's "declaring type".
+ * Return <code>null</code> if the type is a top-level type.
+ */
+ String getDeclaringTypeName();
+ String DECLARING_TYPE_NAME_PROPERTY = "declaringTypeName"; //$NON-NLS-1$
+
+ /**
* Return whether the type is abstract.
*/
boolean isAbstract();
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/utility/BodySourceWriter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/utility/BodySourceWriter.java
new file mode 100644
index 0000000000..0be7b18053
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/utility/BodySourceWriter.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 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.utility;
+
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeSet;
+
+import org.eclipse.jpt.utility.Filter;
+import org.eclipse.jpt.utility.IndentingPrintWriter;
+import org.eclipse.jpt.utility.internal.CollectionTools;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.Transformer;
+import org.eclipse.jpt.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
+
+import com.ibm.icu.text.Collator;
+
+/**
+ * Extend {@link IndentingPrintWriter} with some methods that facilitate
+ * building class source code.
+ */
+@SuppressWarnings("nls")
+public class BodySourceWriter
+ extends IndentingPrintWriter
+{
+ protected final String packageName;
+ protected final String className;
+ // key = short class name; value = import package
+ protected final HashMap<String, ImportPackage> imports = new HashMap<String, ImportPackage>();
+
+ public BodySourceWriter(String packageName, String className) {
+ super(new StringWriter(2000));
+ this.packageName = packageName;
+ this.className = className;
+ }
+
+ public String getSource() {
+ return this.out.toString();
+ }
+
+ public int getLength() {
+ return ((StringWriter) this.out).getBuffer().length();
+ }
+
+ protected void printVisibility(String visibilityModifier) {
+ if (visibilityModifier.length() != 0) {
+ this.print(visibilityModifier);
+ this.print(' ');
+ }
+ }
+
+ public void printAnnotation(String annotationName) {
+ this.print('@');
+ this.printTypeDeclaration(annotationName);
+ }
+
+ public void printTypeDeclaration(String typeDeclaration) {
+ this.print(this.buildImportedTypeDeclaration(typeDeclaration));
+ }
+
+ protected void printField(String fieldName, String typeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(typeDeclaration);
+ this.print(' ');
+ this.print(fieldName);
+ this.print(';');
+ this.println();
+ this.println();
+ }
+
+ protected void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) {
+ this.printVisibility(visibility);
+ this.printTypeDeclaration(typeDeclaration);
+ this.print('<');
+ this.printTypeDeclaration(parameterTypeDeclaration);
+ this.print('>');
+ this.print(' ');
+ this.print(fieldName);
+ this.print(';');
+ this.println();
+ this.println();
+ }
+
+ /**
+ * Convert the specified string to a <em>String Literal</em> and print it,
+ * adding the surrounding double-quotes and escaping characters
+ * as necessary.
+ */
+ public void printStringLiteral(String string) {
+ StringTools.convertToJavaStringLiteralOn(string, this);
+ }
+
+
+ // ********** imports **********
+
+ // ***** writing
+ /**
+ * Return the specified class's "imported" name.
+ * The class declaration must be of the form:
+ * "int"
+ * "int[]" (not "[I")
+ * "java.lang.Object"
+ * "java.lang.Object[]" (not "[Ljava.lang.Object;")
+ * "java.util.Map.Entry" (not "java.util.Map$Entry")
+ * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;")
+ *
+ * To really do this right, we would need to gather all the types from
+ * the "unamed" (default) package that were referenced in the
+ * compilation unit beforehand. *Any* collisions with one of these
+ * types would have to be fully qualified (whether it was from
+ * 'java.lang' or the same package as the current compilation unit).
+ * In other words, if we have any types from the "unnamed" package,
+ * results are unpredictable....
+ */
+ protected String buildImportedTypeDeclaration(String typeDeclaration) {
+ if (this.typeDeclarationIsMemberClass(typeDeclaration)) {
+ // no need for an import, just return the partially-qualified name
+ return this.buildMemberClassTypeDeclaration(typeDeclaration);
+ }
+ int last = typeDeclaration.lastIndexOf('.');
+ String currentPackageName = (last == -1) ? "" : typeDeclaration.substring(0, last);
+ String shortTypeDeclaration = typeDeclaration.substring(last + 1);
+ String shortElementTypeName = shortTypeDeclaration;
+ while (shortElementTypeName.endsWith("[]")) {
+ shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2);
+ }
+ ImportPackage prev = this.imports.get(shortElementTypeName);
+ if (prev == null) {
+ // this is the first class with this short element type name
+ this.imports.put(shortElementTypeName, new ImportPackage(currentPackageName));
+ return shortTypeDeclaration;
+ }
+ if (prev.packageName.equals(currentPackageName)) {
+ // this element type has already been imported
+ return shortTypeDeclaration;
+ }
+ if (currentPackageName.equals(this.packageName) &&
+ prev.packageName.equals("java.lang")) {
+ // we force the 'java.lang' class to be explicitly imported
+ prev.collision = true;
+ }
+ // another class with the same short element type name has been
+ // previously imported, so this one must be used fully-qualified
+ return typeDeclaration;
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return true
+ */
+ protected boolean typeDeclarationIsMemberClass(String typeDeclaration) {
+ return (typeDeclaration.length() > this.className.length())
+ && typeDeclaration.startsWith(this.className)
+ && (typeDeclaration.charAt(this.className.length()) == '.');
+ }
+
+ /**
+ * e.g. "foo.bar.Employee.PK" will return "Employee.PK"
+ * this prevents collisions with other imported classes (e.g. "joo.jar.PK")
+ */
+ protected String buildMemberClassTypeDeclaration(String typeDeclaration) {
+ int index = this.packageName.length();
+ if (index != 0) {
+ index++; // bump past the '.'
+ }
+ return typeDeclaration.substring(index);
+ }
+
+ // ***** reading
+ public Iterable<String> getImports() {
+ return this.getSortedRequiredImports();
+ }
+
+ /**
+ * transform our map entries to class names
+ */
+ protected Iterable<String> getSortedRequiredImports() {
+ return new TransformationIterable<Map.Entry<String, ImportPackage>, String>(this.getSortedRequiredImportEntries(), this.buildImportEntriesTransformer());
+ }
+
+ protected Transformer<Map.Entry<String, ImportPackage>, String> buildImportEntriesTransformer() {
+ return IMPORT_ENTRIES_TRANSFORMER;
+ }
+
+ protected static final Transformer<Map.Entry<String, ImportPackage>, String> IMPORT_ENTRIES_TRANSFORMER = new ImportEntriesTransformer();
+
+ protected static class ImportEntriesTransformer
+ implements Transformer<Map.Entry<String, ImportPackage>, String>
+ {
+ public String transform(Entry<String, ImportPackage> importEntry) {
+ String pkg = importEntry.getValue().packageName;
+ String type = importEntry.getKey();
+ StringBuilder sb = new StringBuilder(pkg.length() + 1 + type.length());
+ sb.append(pkg);
+ sb.append('.');
+ sb.append(type);
+ return sb.toString();
+ }
+ }
+
+ /**
+ * sort by package first, then class (*not* by fully-qualified class name)
+ */
+ protected Iterable<Map.Entry<String, ImportPackage>> getSortedRequiredImportEntries() {
+ TreeSet<Map.Entry<String, ImportPackage>> sortedEntries = new TreeSet<Map.Entry<String, ImportPackage>>(this.buildImportEntriesComparator());
+ CollectionTools.addAll(sortedEntries, this.getRequiredImportEntries());
+ return sortedEntries;
+ }
+
+ protected Comparator<Map.Entry<String, ImportPackage>> buildImportEntriesComparator() {
+ return IMPORT_ENTRIES_COMPARATOR;
+ }
+
+ protected static final Comparator<Map.Entry<String, ImportPackage>> IMPORT_ENTRIES_COMPARATOR = new ImportEntriesComparator();
+
+ protected static class ImportEntriesComparator
+ implements Comparator<Map.Entry<String, ImportPackage>>, Serializable
+ {
+ public int compare(Map.Entry<String, ImportPackage> e1, Map.Entry<String, ImportPackage> e2) {
+ Collator collator = Collator.getInstance();
+ int pkg = collator.compare(e1.getValue().packageName, e2.getValue().packageName);
+ return (pkg == 0) ? collator.compare(e1.getKey(), e2.getKey()) : pkg;
+ }
+ }
+
+ /**
+ * strip off any non-required imports (e.g. "java.lang.Object')
+ */
+ protected Iterable<Map.Entry<String, ImportPackage>> getRequiredImportEntries() {
+ return new FilteringIterable<Map.Entry<String, ImportPackage>>(this.imports.entrySet(), this.buildRequiredImportEntriesFilter());
+ }
+
+ protected Filter<Map.Entry<String, ImportPackage>> buildRequiredImportEntriesFilter() {
+ return new RequiredImportEntriesFilter();
+ }
+
+ protected class RequiredImportEntriesFilter
+ implements Filter<Map.Entry<String, ImportPackage>>
+ {
+ public boolean accept(Map.Entry<String, ImportPackage> importEntry) {
+ return this.packageMustBeImported(importEntry.getValue());
+ }
+
+ protected boolean packageMustBeImported(ImportPackage importPackage) {
+ String pkg = importPackage.packageName;
+ if (pkg.equals("")) {
+ // cannot import a type from the "unnamed" package
+ return false;
+ }
+ if (pkg.equals("java.lang")) {
+ // we must import from 'java.lang' if we also have a class in the same package
+ return importPackage.collision;
+ }
+ if (pkg.equals(BodySourceWriter.this.packageName)) {
+ // we never need to import a class from the same package
+ return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * We need a 'collision' flag for when we encounter a class from
+ * 'java.lang' followed by a class from the current compilation unit's
+ * package. We will need to include the explicit import of the
+ * 'java.lang' class and all the references to the other class will
+ * have to be fully-qualified.
+ *
+ * If the classes are encountered in the opposite order (i.e. the class
+ * from the current compilation unit's package followed by the class
+ * from 'java.lang'), we do *not* need to import the first class while
+ * all the references to the 'java.lang' class will be fully-qualified.
+ *
+ * Unfortunately, we still have a problem: if we reference a class from
+ * 'java.lang' and there is a conflicting class from the current
+ * compilation unit's package (but that class is *not* revealed to us
+ * here), the simple name will be resolved to the non-'java.lang' class.
+ * Unless we simply force an import of *all* 'java.lang' classes.... :-(
+ *
+ * This shouldn't happen very often. :-)
+ */
+ protected static class ImportPackage {
+ protected final String packageName;
+ protected boolean collision = false;
+
+ protected ImportPackage(String packageName) {
+ super();
+ this.packageName = packageName;
+ }
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
index 06bf6b944a..023a1a807e 100644
--- a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/v2_0/EclipseLink2_0JpaFactory.java
@@ -27,7 +27,7 @@ import org.eclipse.jpt.core.context.java.JavaSequenceGenerator;
import org.eclipse.jpt.core.context.java.JavaBaseColumn.Owner;
import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaAssociationOverrideContainer;
import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaColumn;
-import org.eclipse.jpt.core.internal.jpa2.GenericPersistentTypeMetamodelSynchronizer;
+import org.eclipse.jpt.core.internal.jpa2.GenericMetamodelSynchronizer;
import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaAssociationOverrideRelationshipReference2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaCacheable2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaCollectionTable2_0;
@@ -40,6 +40,7 @@ import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaPersistentType
import org.eclipse.jpt.core.internal.jpa2.context.java.GenericJavaSequenceGenerator2_0;
import org.eclipse.jpt.core.internal.jpa2.context.java.VirtualAssociationOverride2_0Annotation;
import org.eclipse.jpt.core.jpa2.JpaProject2_0;
+import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType;
import org.eclipse.jpt.core.jpa2.context.PersistentType2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheable2_0;
import org.eclipse.jpt.core.jpa2.context.java.JavaCacheableHolder2_0;
@@ -81,8 +82,8 @@ public class EclipseLink2_0JpaFactory
}
@Override
- public PersistentType2_0.MetamodelSynchronizer buildPersistentTypeMetamodelSynchronizer(PersistentType2_0 persistentType) {
- return new GenericPersistentTypeMetamodelSynchronizer(persistentType);
+ public MetamodelSourceType.Synchronizer buildMetamodelSynchronizer(MetamodelSourceType sourceType) {
+ return new GenericMetamodelSynchronizer(sourceType);
}
// ********** Java Context Model **********
diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/IndentingPrintWriter.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/IndentingPrintWriter.java
index a712c7ac62..35fa70a79b 100644
--- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/IndentingPrintWriter.java
+++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/IndentingPrintWriter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2005, 2010 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.
@@ -7,7 +7,7 @@
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
-package org.eclipse.jpt.utility.internal;
+package org.eclipse.jpt.utility;
import java.io.PrintWriter;
import java.io.Writer;
@@ -15,8 +15,9 @@ import java.io.Writer;
/**
* Extend {@link PrintWriter} to automatically indent new lines.
*/
-public class IndentingPrintWriter extends PrintWriter {
-
+public class IndentingPrintWriter
+ extends PrintWriter
+{
private final String indent;
private int indentLevel;
private boolean needsIndent;
@@ -141,10 +142,13 @@ public class IndentingPrintWriter extends PrintWriter {
/**
* Allow the indent level to be set directly.
+ * Return the previous indent level.
*/
- public void setIndentLevel(int indentLevel) {
+ public int setIndentLevel(int indentLevel) {
synchronized (this.lock) {
+ int old = this.indentLevel;
this.indentLevel = indentLevel;
+ return old;
}
}
diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java
index 93a577956c..7c3ecf1fc2 100644
--- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java
+++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java
@@ -57,8 +57,8 @@ import org.eclipse.jpt.db.Sequence;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.db.ForeignKey.ColumnPair;
import org.eclipse.jpt.db.tests.internal.JptDbTestsPlugin;
+import org.eclipse.jpt.utility.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.ReflectionTools;
-import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.ResultSetIterator;
diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/ClassNameTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/ClassNameTests.java
index 5588858142..3b31f37e9a 100644
--- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/ClassNameTests.java
+++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/ClassNameTests.java
@@ -69,6 +69,9 @@ public class ClassNameTests extends TestCase {
assertEquals("Object[]", ClassName.getSimpleName(java.lang.Object[].class.getName()));
assertEquals("Object[][]", ClassName.getSimpleName(java.lang.Object[][].class.getName()));
+ assertEquals(java.util.Map.class.getSimpleName(), ClassName.getSimpleName(java.util.Map.class.getName()));
+ assertEquals(java.util.Map.Entry.class.getSimpleName(), ClassName.getSimpleName(java.util.Map.Entry.class.getName()));
+
assertEquals("int", ClassName.getSimpleName(int.class.getName()));
assertEquals("int[]", ClassName.getSimpleName(int[].class.getName()));
assertEquals("int[][]", ClassName.getSimpleName(int[][].class.getName()));
@@ -86,10 +89,13 @@ public class ClassNameTests extends TestCase {
}
public void testGetPackageName() throws Exception {
- assertEquals("java.lang", ClassName.getPackageName(java.lang.Object.class.getName()));
+ assertEquals(java.lang.Object.class.getPackage().getName(), ClassName.getPackageName(java.lang.Object.class.getName()));
assertEquals("", ClassName.getPackageName(java.lang.Object[].class.getName()));
assertEquals("", ClassName.getPackageName(java.lang.Object[][].class.getName()));
+ assertEquals(java.util.Map.class.getPackage().getName(), ClassName.getPackageName(java.util.Map.class.getName()));
+ assertEquals(java.util.Map.Entry.class.getPackage().getName(), ClassName.getPackageName(java.util.Map.Entry.class.getName()));
+
assertEquals("", ClassName.getPackageName(int.class.getName()));
assertEquals("", ClassName.getPackageName(int[].class.getName()));
assertEquals("", ClassName.getPackageName(int[][].class.getName()));
diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/IndentingPrintWriterTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/IndentingPrintWriterTests.java
index f91064f4a6..cb19b1c640 100644
--- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/IndentingPrintWriterTests.java
+++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/IndentingPrintWriterTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2005, 2010 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.
@@ -11,7 +11,8 @@ package org.eclipse.jpt.utility.tests.internal;
import java.io.StringWriter;
import junit.framework.TestCase;
-import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
+
+import org.eclipse.jpt.utility.IndentingPrintWriter;
@SuppressWarnings("nls")
public class IndentingPrintWriterTests extends TestCase {
diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/model/value/swing/TreeModelAdapterTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/model/value/swing/TreeModelAdapterTests.java
index 257096ce20..760d17b36c 100644
--- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/model/value/swing/TreeModelAdapterTests.java
+++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/model/value/swing/TreeModelAdapterTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2010 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.
@@ -24,8 +24,8 @@ import javax.swing.tree.TreeModel;
import junit.framework.TestCase;
+import org.eclipse.jpt.utility.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.HashBag;
-import org.eclipse.jpt.utility.internal.IndentingPrintWriter;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.ReadOnlyIterator;
import org.eclipse.jpt.utility.internal.model.AbstractModel;

Back to the top