Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java')
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa2/GenericPersistentTypeMetamodelSynchronizer.java604
1 files changed, 0 insertions, 604 deletions
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;
- }
- }
-
- }
-
-}

Back to the top