diff options
author | nhauge | 2009-03-11 03:28:11 +0000 |
---|---|---|
committer | nhauge | 2009-03-11 03:28:11 +0000 |
commit | 1d908333499a3351bf79de5ebc27a953addc5c17 (patch) | |
tree | 4dfac0347008a8124a16b5725c08a0a8102ec2e3 | |
parent | dc3c74146ae38cb08d839474e6a6dfc95f9bd37d (diff) | |
download | webtools.dali-1d908333499a3351bf79de5ebc27a953addc5c17.tar.gz webtools.dali-1d908333499a3351bf79de5ebc27a953addc5c17.tar.xz webtools.dali-1d908333499a3351bf79de5ebc27a953addc5c17.zip |
[251293] Initial check-in for entity generation contribution. Added dependency on apache commons, commons.lang, and oro from orbit Temporarily added local dependency on velocity-1.5 until it is also included in orbit.
105 files changed, 11432 insertions, 7 deletions
diff --git a/jpa/features/org.eclipse.jpt.feature/feature.xml b/jpa/features/org.eclipse.jpt.feature/feature.xml index 4288ecfa50..509f764031 100644 --- a/jpa/features/org.eclipse.jpt.feature/feature.xml +++ b/jpa/features/org.eclipse.jpt.feature/feature.xml @@ -73,4 +73,25 @@ version="0.0.0" unpack="false"/> + <plugin + id="org.apache.commons.collections" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.apache.commons.lang" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + + <plugin + id="org.apache.oro" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + </feature> diff --git a/jpa/plugins/org.eclipse.jpt.gen/.classpath b/jpa/plugins/org.eclipse.jpt.gen/.classpath index 8f257414e6..731b00f305 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/.classpath +++ b/jpa/plugins/org.eclipse.jpt.gen/.classpath @@ -2,6 +2,7 @@ <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="src" path="property_files"/> + <classpathentry exported="true" kind="lib" path="lib/velocity-1.5.jar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="output" path="bin"/> diff --git a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF index b6698a3e63..ee9c80a83e 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF +++ b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF @@ -3,12 +3,20 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-SymbolicName: org.eclipse.jpt.gen -Bundle-Version: 1.2.100.qualifier -Bundle-ClassPath: . +Bundle-Version: 1.3.0.qualifier +Bundle-ClassPath: ., + lib/velocity-1.5.jar Bundle-Localization: plugin -Export-Package: org.eclipse.jpt.gen.internal; x-friends:="org.eclipse.jpt.ui" +Export-Package: org.eclipse.jpt.gen.internal;x-friends:="org.eclipse.jpt.ui", + org.eclipse.jpt.gen.internal2, + org.eclipse.jpt.gen.internal2.util Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.eclipse.jdt.core;bundle-version="[3.4.0,4.0.0)", org.eclipse.jpt.utility;bundle-version="[1.2.0,2.0.0)", - org.eclipse.jpt.db;bundle-version="[1.2.0,2.0.0)" + org.eclipse.jpt.db;bundle-version="[1.2.0,2.0.0)", + org.eclipse.core.resources;bundle-version="[3.4.0,4.0.0)", + org.eclipse.jface.text;bundle-version="[3.4.0,4.0.0)", + org.apache.commons.collections;bundle-version="3.2.0", + org.apache.commons.lang;bundle-version="2.1.0", + org.apache.oro;bundle-version="2.0.8" Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/jpa/plugins/org.eclipse.jpt.gen/build.properties b/jpa/plugins/org.eclipse.jpt.gen/build.properties index a1fd5b8411..038c63b3f2 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/build.properties +++ b/jpa/plugins/org.eclipse.jpt.gen/build.properties @@ -13,5 +13,6 @@ output.. = bin/ bin.includes = .,\ META-INF/,\ about.html,\ - plugin.properties + plugin.properties,\ + lib/velocity-1.5.jar jars.compile.order = . diff --git a/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar b/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar Binary files differnew file mode 100644 index 0000000000..7c7f2c43b4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/lib/velocity-1.5.jar diff --git a/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties b/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties index 03e8908d0e..3427be198d 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties +++ b/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties @@ -11,3 +11,6 @@ PackageGenerator_taskName=Generate Entities GenScope_taskName=Build Database Model EntityGenerator_taskName=Generate Entity: {0} +Error_Generating_Entities = Error Generating Entities; + +Templates_notFound = Unable to find JPA entities generation templates in plugin
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java index bc3bbf0d38..b765abd340 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java @@ -19,6 +19,7 @@ class JptGenMessages { public static String PackageGenerator_taskName; public static String GenScope_taskName; public static String EntityGenerator_taskName; + public static String Templates_notFound; private static final String BUNDLE_NAME = "jpt_gen"; //$NON-NLS-1$ private static final Class<?> BUNDLE_CLASS = JptGenMessages.class; diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java new file mode 100644 index 0000000000..aef08c4221 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/Association.java @@ -0,0 +1,387 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import java.util.List; + +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.gen.internal2.util.StringUtil; + +/** + * Represents an ORM association. + * There are two types of associations: + * <ul><li>simple association: An association between two database tables. + * The <em>referrer</code> table is the one containing the foreign key + * , the <em>referenced</code> table is the other party.<br> + * + * <li>many to many association: An association between two tables joined by + * a <em>join table</em>. + * In the example AUTHOR, BOOK, AUTHOR_BOOK, The referrer and referenced are + * AUTHOR and BOOK, and the join table is AUTHOR_BOOK. + * </ul> + * + */ +public class Association implements java.io.Serializable +{ + private final static long serialVersionUID = 2; + + public static final String MANY_TO_ONE = "many-to-one"; + public static final String MANY_TO_MANY = "many-to-many"; + public static final String ONE_TO_ONE = "one-to-one"; + public static final String ONE_TO_MANY = "one-to-many"; + + public static final String BI_DI = "bi-di"; + public static final String NORMAL_DI = "normal-di"; //referrer->referenced + public static final String OPPOSITE_DI = "opposite-di"; //referenced->referrer + + private transient ORMGenCustomizer mCustomizer; + private String mReferrerTableName; + private String mReferencedTableName; + private String mJoinTableName; + + private List<String> mReferrerColNames; /*String objects*/ + private List<String> mReferencedColNames; /*String objects*/ + private List<String> mReferrerJoinColNames; /*String objects*/ + private List<String> mReferencedJoinColNames; /*String objects*/ + + private transient List<ORMGenColumn> mReferrerCols; /*ORMGenColumn objects*/ + private transient List<ORMGenColumn> mReferencedCols; /*ORMGenColumn objects*/ + private transient List<ORMGenColumn> mReferrerJoinCols; /*ORMGenColumn objects*/ + private transient List<ORMGenColumn> mReferencedJoinCols; /*ORMGenColumn objects*/ + + private String mCardinality; + private String mDirectionality; + private byte mFlags = GENERATED; + + private AssociationRole mReferrerRole; + private AssociationRole mReferencedRole; + + private transient ForeignKey mForeignKey; + + /*constants for mFlags*/ + /*whether the association should be generated*/ + private static final byte GENERATED = 1 << 0; + /*whether the association is custom (i.e is not auto computed from foreign keys relationships).*/ + private static final byte CUSTOM = 1 << 1; + + /** + * The simple association constructor. + * The 2 tables are joined when the values of each column in + * referrerColNames match its corresponding column in referencedColNames. + * + * @param referrerTableName The "foreign key" table. + * @param referrerColNames The column names in the referrer table. + * @param referencedTableName The "primary key" table. + * @param referencedColNames The column names in the referenced table. + */ + public Association(ORMGenCustomizer customizer, String referrerTableName, List<String> referrerColNames + , String referencedTableName, List<String> referencedColNames) { + super(); + + mCustomizer = customizer; + mReferrerTableName = referrerTableName; + mReferencedTableName = referencedTableName; + mReferrerColNames = referrerColNames; + mReferencedColNames = referencedColNames; + + mCardinality = MANY_TO_ONE; + mDirectionality = BI_DI; + + setCustom(true); + } + /** + * The many to many constructor. + * The 2 tables are joined when the values of each column in + * referrerColNames match its corresponding column in referrerJoinColNames + * , and each column in referencedColNames match its corresponding column in referencedJoinColNames. + * + */ + public Association(ORMGenCustomizer customizer, String referrerTableName, List<String> referrerColNames + , String referencedTableName, List<String> referencedColNames + , String joinTableName, List<String> referrerJoinColNames, List<String> referencedJoinColNames) { + super(); + + mCustomizer = customizer; + mReferrerTableName = referrerTableName; + mReferencedTableName = referencedTableName; + mReferrerColNames = referrerColNames; + mReferencedColNames = referencedColNames; + mJoinTableName = joinTableName; + mReferrerJoinColNames = referrerJoinColNames; + mReferencedJoinColNames = referencedJoinColNames; + + mCardinality = MANY_TO_MANY; + mDirectionality = BI_DI; + + setCustom(true); + } + /** + * Empty constructor needed by the deserialization (should not be used otherwise). + */ + public Association() { + } + /** + * Computes the cardinality basedon the forign key definitions. + */ + public void computeCardinality() { + /*by default the association is many-to-one unless the foreign key + * is also the primary key, in which case it is a one-to-one.*/ + mCardinality = MANY_TO_ONE; + + List<ORMGenColumn> referrerCols = getReferrerColumns(); + List<ORMGenColumn> pkCols = getReferrerTable().getPrimaryKeyColumns(); + if (pkCols.size() == referrerCols.size()) { + boolean isFkPk = true; + for (int i = 0, n = pkCols.size(); i < n; ++i) { + if (!((ORMGenColumn)pkCols.get(i)).getName().equals(((ORMGenColumn)referrerCols.get(i)).getName())) { + isFkPk = false; + break; + } + } + if (isFkPk) { + mCardinality = ONE_TO_ONE; + } + } + + setCustom(false); + } + /** + * Called after the asscociations are deserialized to attach + * the customizer object. + */ + protected void restore(ORMGenCustomizer customizer) { + mCustomizer = customizer; + + if (mReferrerRole != null) { + mReferrerRole.restore(this); + } + if (mReferencedRole != null) { + mReferencedRole.restore(this); + } + } + public ORMGenTable getReferrerTable() { + return mCustomizer.getTable(mReferrerTableName); + } + public String getReferrerTableName() { + return mReferrerTableName; + } + public ORMGenTable getReferencedTable() { + return mCustomizer.getTable(mReferencedTableName); + } + public String getReferencedTableName() { + return mReferencedTableName; + } + public ORMGenTable getJoinTable() { + return mCustomizer.getTable(mJoinTableName); + } + public String getJoinTableName() { + return mJoinTableName; + } + /** + * Returns the <code>ORMGenColumn</code> objects for the referrer + * columns. + */ + public List<ORMGenColumn> getReferrerColumns() { + if (mReferrerCols == null) { + mReferrerCols = getReferrerTable().getColumnsByNames(mReferrerColNames); + } + return mReferrerCols; + } + public List<String> getReferrerColumnNames() { + return mReferrerColNames; + } + /** + * Returns the <code>ORMGenColumn</code> objects for the referenced + * columns. + */ + public List<ORMGenColumn> getReferencedColumns() { + if (mReferencedCols == null) { + mReferencedCols = getReferencedTable().getColumnsByNames(mReferencedColNames); + } + return mReferencedCols; + } + public List<String> getReferencedColumnNames() { + return mReferencedColNames; + } + public List<ORMGenColumn> getReferrerJoinColumns() { + if (mReferrerJoinCols == null) { + mReferrerJoinCols = getJoinTable().getColumnsByNames(mReferrerJoinColNames); + } + return mReferrerJoinCols; + } + public List<String> getReferrerJoinColumnNames() { + return mReferrerJoinColNames; + } + public List<ORMGenColumn> getReferencedJoinColumns() { + if (mReferencedJoinCols == null) { + mReferencedJoinCols = getJoinTable().getColumnsByNames(mReferencedJoinColNames); + } + return mReferencedJoinCols; + } + public List<String> getReferencedJoinColumnNames() { + return mReferencedJoinColNames; + } + /** + * Returns the association cardinality, one of {@link #MANY_TO_ONE}|{@link #MANY_TO_MANY} + * |{@link #ONE_TO_ONE}|{@link #ONE_TO_MANY} + */ + public String getCardinality() { + return mCardinality; + } + public void setCardinality(String cardinality) { + assert(cardinality.equals(MANY_TO_ONE) || cardinality.equals(MANY_TO_MANY) || cardinality.equals(ONE_TO_ONE) || cardinality.equals(ONE_TO_MANY)); + mCardinality = cardinality; + } + /** + * Returns the association directionality, one of {@link #BI_DI}|{@link #NORMAL_DI} + * |{@link #OPPOSITE_DI} + */ + public String getDirectionality() { + return mDirectionality; + } + public void setDirectionality(String dir) { + assert(dir.equals(BI_DI) || dir.equals(NORMAL_DI) || dir.equals(OPPOSITE_DI)); + if (!dir.equals(mDirectionality)) { + mDirectionality = dir; + + if (dir.equals(NORMAL_DI)) { + mReferencedRole = null; + } else if (dir.equals(OPPOSITE_DI)) { + mReferrerRole = null; + } + } + } + + /** + * Tests whether this association is bidirectional. + * This is a shortcut for <code>getDirectionality().equals(BI_DI)</code>. + */ + public boolean isBidirectional() { + return mDirectionality.equals(BI_DI); + } + /** + * Returns true of this association should be generated. + */ + public boolean isGenerated() { + return (mFlags & GENERATED) != 0; + } + public void setGenerated(boolean generated) { + if (generated != isGenerated()) { + if (generated) { + mFlags |= GENERATED; + } else { + mFlags &= ~GENERATED; + } + mReferrerRole = mReferencedRole = null; + } + } + /** + * Returns true of this association is custom (i.e is not auto computed from foreign keys relationships). + */ + public boolean isCustom() { + return (mFlags & CUSTOM) != 0; + } + public void setCustom(boolean custom) { + if (custom) { + mFlags |= CUSTOM; + } else { + mFlags &= ~CUSTOM; + } + } + /** + * Returns the association role for the referrer side, or null + * if none (i.e if the directionality does not include it). + */ + public AssociationRole getReferrerRole() { + if (mReferrerRole == null && isGenerated()) { + if (!getDirectionality().equals(OPPOSITE_DI)) { //BI_DI or NORMAL_DI + mReferrerRole = new AssociationRole(this, true/*isReferrerEnd*/); + } + } + return mReferrerRole; + } + /** + * Returns the association role for the referenced side, or null + * if none (i.e if the directionality does not include it). + */ + public AssociationRole getReferencedRole() { + if (mReferencedRole == null && isGenerated()) { + if (!getDirectionality().equals(Association.NORMAL_DI)) { //BI_DI or OPPOSITE_DI + mReferencedRole = new AssociationRole(this, false/*isReferrerEnd*/); + } + } + return mReferencedRole; + } + /** + * Tests whether this association is valid (valid table and column names). + */ + protected boolean isValid(){ + if (!isValidTableAndColumns(mReferrerTableName, mReferrerColNames) + || !isValidTableAndColumns(mReferencedTableName, mReferencedColNames)) { + return false; + } + if (mJoinTableName != null) { + if (!isValidTableAndColumns(mJoinTableName, mReferrerJoinColNames) + || !isValidTableAndColumns(mJoinTableName, mReferencedJoinColNames)) { + return false; + } + } + return true; + } + private boolean isValidTableAndColumns(String tableName, List<String> columnNames) { + ORMGenTable table = mCustomizer.getTable(tableName); + if (table == null) { + return false; + } + for (int i = 0, n = columnNames.size(); i < n; ++i) { + String colName = (String)columnNames.get(i); + if (table.getColumnByName(colName) == null) { + return false; + } + } + return true; + } + + public void setForeignKey(ForeignKey foreignKey) { + this.mForeignKey = foreignKey; + + } + public ForeignKey getForeignKey(){ + return this.mForeignKey; + }; + public boolean equals(Object obj) { + if( this == obj ) + return true; + if( obj instanceof Association ){ + Association association2 = (Association)obj; + if (!this.getReferrerTableName().equals(association2.getReferrerTableName()) + || !this.getReferencedTableName().equals(association2.getReferencedTableName()) + || !StringUtil.equalObjects(this.getJoinTableName(), association2.getJoinTableName()) + || !this.getReferrerColumnNames().equals(association2.getReferrerColumnNames()) + || !this.getReferencedColumnNames().equals(association2.getReferencedColumnNames()) + ) { + return false; + } + /*the 2 association have the same referrer, referenced and join table*/ + //If MTO or OTM association + if (this.getJoinTableName() == null) { + return true; + } + if (this.getReferrerJoinColumnNames().equals(association2.getReferrerJoinColumnNames()) + && this.getReferencedJoinColumnNames().equals(association2.getReferencedJoinColumnNames())) { + return true; + } + } + return false; + } + public String toString(){ + return mReferrerTableName + " " + mCardinality + " " + mReferencedTableName ; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java new file mode 100644 index 0000000000..458edfd58e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/AssociationRole.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import java.util.Iterator; +import java.util.List; + +/** + * Represents an association role (the referrer or referenced role). + * + */ +public class AssociationRole implements java.io.Serializable +{ + private transient Association mAssociation; //transient: see restore + private boolean mIsReferrerRole; + private String mPropertyName; + private String mCascade; + + private final static long serialVersionUID = 1; + + AssociationRole(Association association, boolean isReferrerRole) { + super(); + + mAssociation = association; + mIsReferrerRole = isReferrerRole; + } + /** + * Empty constructor needed by the deserialization (should not be used otherwise). + */ + public AssociationRole() { + } + /** + * Called after the asscociations are deserialized to attach + * the customizer object. + */ + protected void restore(Association association) { + mAssociation = association; + } + public Association getAssociation() { + return mAssociation; + } + public boolean isReferrerRole() { + return mIsReferrerRole; + } + /** + * Returns the opposite role or null if the association + * is not bi directional. + */ + public AssociationRole getOppositeRole() { + Association association = getAssociation(); + if (!association.getDirectionality().equals(Association.BI_DI)) { + return null; + } + if (isReferrerRole()) { + return association.getReferencedRole(); + } else { + return association.getReferrerRole(); + } + } + /** + * Returns the association cardinality, one of {@link #MANY_TO_ONE}|{@link #MANY_TO_MANY} + * |{@link #ONE_TO_ONE}|{@link #ONE_TO_MANY} + */ + public String getCardinality() { + String type = mAssociation.getCardinality(); + if (!mIsReferrerRole) { + if (type.equals(Association.ONE_TO_MANY)) { + type = Association.MANY_TO_ONE; + } else if (type.equals(Association.MANY_TO_ONE)) { + type = Association.ONE_TO_MANY; + } + } + return type; + } + public ORMGenTable getReferrerTable() { + if (mIsReferrerRole) { + return mAssociation.getReferrerTable(); + } else { + return mAssociation.getReferencedTable(); + } + } + public List<ORMGenColumn> getReferrerColumns(){ + if (mIsReferrerRole) { + return mAssociation.getReferrerColumns(); + } else { + return mAssociation.getReferencedColumns(); + } + } + /** + * Returns the referenced column corresponding to a referrer column. + */ + public ORMGenColumn getReferencedColumn(String referrerColumn) { + boolean hasJoinTable = mAssociation.getJoinTable() != null; + List<ORMGenColumn> referrerColumns = getReferrerColumns(); + for (int i = 0, n = referrerColumns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)referrerColumns.get(i); + if (column.getName().equals(referrerColumn)) { + if (hasJoinTable) { + return (ORMGenColumn)getReferrerJoinColumns().get(i); + } else { + return (ORMGenColumn)getReferencedColumns().get(i); + } + } + } + assert(false); + return null; + } + /** + * Returns the referrer column corresponding to a referenced column. + */ + public ORMGenColumn getReferrerColumn(String referencedColumn) { + boolean hasJoinTable = mAssociation.getJoinTable() != null; + List<ORMGenColumn> referencedColumns = getReferencedColumns(); + for (int i = 0, n = referencedColumns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)referencedColumns.get(i); + if (column.getName().equals(referencedColumn)) { + if (hasJoinTable) { + return (ORMGenColumn)getReferencedJoinColumns().get(i); + } else { + return (ORMGenColumn)getReferrerColumns().get(i); + } + } + } + assert(false); + return null; + } + public ORMGenTable getReferencedTable() { + if (mIsReferrerRole) { + return mAssociation.getReferencedTable(); + } else { + return mAssociation.getReferrerTable(); + } + } + public List<ORMGenColumn> getReferencedColumns() { + if (mIsReferrerRole) { + return mAssociation.getReferencedColumns(); + } else { + return mAssociation.getReferrerColumns(); + } + } + public List<ORMGenColumn> getReferrerJoinColumns() { + if (mIsReferrerRole) { + return mAssociation.getReferrerJoinColumns(); + } else { + return mAssociation.getReferencedJoinColumns(); + } + } + public List<ORMGenColumn> getReferencedJoinColumns() { + if (mIsReferrerRole) { + return mAssociation.getReferencedJoinColumns(); + } else { + return mAssociation.getReferrerJoinColumns(); + } + } + + /** + * Returns the name that should be used by the generator for + * the property corresponding to this role. + */ + public String getPropertyName() { + if (mPropertyName != null) { //if the user explicitly set it then don't be too smart + return mPropertyName; + } + String propName =""; + ORMGenTable referrerTable = getReferrerTable(); + ORMGenTable referencedTable = getReferencedTable(); + + boolean isSingular = isSingular(); + propName = referencedTable.getVarName(isSingular); + + List<AssociationRole> clashingRoles = new java.util.ArrayList<AssociationRole>(); //roles with our same referrer and referenced tables (i.e would yield the same property name in the same bean) + /*make sure there is no role with the same name.*/ + for (Iterator<AssociationRole> iter = referrerTable.getAssociationRoles().iterator(); iter.hasNext(); ) { + AssociationRole role = (AssociationRole)iter.next(); + if (role.getReferrerTable().getName().equals(referrerTable.getName()) + && role.getReferencedTable().getName().equals(referencedTable.getName()) + && role.isSingular() == isSingular) { + clashingRoles.add(role); + } + } + if (clashingRoles.size() > 1) { + int index = clashingRoles.indexOf(this); + assert(index >= 0); + propName += index+1; + } + + /*make sure there is no column with the same name.*/ + for (Iterator<ORMGenColumn> iter = referrerTable.getColumns().iterator(); iter.hasNext(); ) { + ORMGenColumn column = (ORMGenColumn)iter.next(); + if (column.getPropertyName().equals(propName)) { + String prefix = isSingular ? "Bean" : "Set"; + propName += prefix; + break; + } + } + + return propName; + } + private boolean isSingular() { + String cardinality = getCardinality(); + return cardinality.equals(Association.ONE_TO_ONE) || cardinality.equals(Association.MANY_TO_ONE); + } + /** + * Changes the name that should be used by the generator for + * the property corresponding to this role. + * If the argument name is null or empty string then the + * default computed name is used. + */ + public void setPropertyName(String name) { + if (name != null && name.length() == 0) { + name = null; + } + if (name != null && name.equals(getPropertyName())) { + name = null; + } + mPropertyName = name; + } + /** + * Returns the cascade value for this role, or null if none. + */ + public String getCascade() { + return mCascade; + } + public void setCascade(String cascade) { + if (cascade != null && cascade.length() == 0) { + cascade = null; + } + mCascade = cascade; + } + /** + * Returns a descriptive string used in a comment in the generated + * file (from the Velocity template). + */ + public String getDescription() { + //<!-- $directionality $cardinality association to $referencedClassName --> + String directionality; + if (getAssociation().getDirectionality().equals(Association.BI_DI)) { + directionality = "bi-directional"; + } else { + directionality = "uni-directional"; + } + return directionality + " " + getAssociation().getCardinality() + " association to " + getReferencedTable().getClassName(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java new file mode 100644 index 0000000000..8b6191c3ca --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/BaseEntityGenCustomizer.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.gen.internal2.util.StringUtil; + +/** + * Default implementation of ORMGenCustomizer according to JPA specification + * for entity generation. + * + * This is used to retrieve/change the properties from the wizard + * and is also passed as a context object to Velocity. + */ +public class BaseEntityGenCustomizer extends ORMGenCustomizer implements java.io.Serializable +{ + private final static long serialVersionUID = 1; + + /*mapping kinds*/ + private static final String BASIC_MAPPING_KIND = "basic"; + private static final String ID_MAPPING_KIND = "id"; + private static final String VERSION_MAPPING_KIND = "version"; + + + /*the strings for generator names. These appear in a combo box + * and used by the Velocity template processing.*/ + private static final String AUTO_GENERATOR = "auto"; + private static final String NONE_GENERATOR = "none"; + private static final String IDENTITY_GENERATOR = "identity"; + private static final String SEQUENCE_GENERATOR = "sequence"; + private static final String TABLE_GENERATOR = "table"; + + public BaseEntityGenCustomizer(){} + + public void init(File file, Schema schema) { + super.init(file, schema); + } + + //----------------------------------------- + //------ ORMGenCustomizer methods + //----------------------------------------- + public List<String> getAllIdGenerators() { + List<String> result = new java.util.ArrayList<String>(5); + /*add in the order in which they would appear in the combo*/ + result.add(AUTO_GENERATOR); + result.add(IDENTITY_GENERATOR); + result.add(SEQUENCE_GENERATOR); + result.add(TABLE_GENERATOR); + result.add(NONE_GENERATOR); + return result; + } + public String getNoIdGenerator() { + return NONE_GENERATOR; + } + public String getIdentityIdGenerator() { + return IDENTITY_GENERATOR; + } + public Set<String> getSequenceIdGenerators() { + Set<String> result = new java.util.HashSet<String>(3); + result.add(AUTO_GENERATOR); + result.add(SEQUENCE_GENERATOR); + + return result; + } + public String getPropertyTypeFromColumn( Column column) { + return DTPUtil.getJavaType( getSchema(), column ); + } + public String[] getAllPropertyTypes() { + /* + * Java primitive types, wrapper of the primitive types + * , java.lang.String, java.math.BigInteger, + * java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, + * java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[], + * enums, and any other type that implements Serializable. + * */ + //return in the order that will be used in the combo + return new String[] { + "boolean" + , "Boolean" + , "byte" + , "Byte" + , "byte[]" + , "char" + , "char[]" + , "Character" + , "Character[]" + , "double" + , "Double" + , "float" + , "Float" + , "int" + , "Integer" + , "long" + , "Long" + , "Object" + , "short" + , "Short" + , "String" + + , java.math.BigDecimal.class.getName() + , java.math.BigInteger.class.getName() + , java.util.Calendar.class.getName() + , java.util.Date.class.getName() + , java.sql.Date.class.getName() + , java.sql.Time.class.getName() + , java.sql.Timestamp.class.getName() + }; + } + public String[] getAllMappingKinds() { + return new String[] { + BASIC_MAPPING_KIND + , ID_MAPPING_KIND + , VERSION_MAPPING_KIND + }; + } + /* (non-Javadoc) + */ + public String getBasicMappingKind() { + return BASIC_MAPPING_KIND; + } + /* (non-Javadoc) + */ + public String getIdMappingKind() { + return ID_MAPPING_KIND; + } + public boolean editCascade(AssociationRole role) { + return false; + } + + protected boolean manySideIsAssociationOwner() { + return true; + } + + //----------------------------------------- + //---- Velocity templates methods + //----------------------------------------- + /** + * Returns the cascades annotation member value, or empty string + * if none. + * Empty string is returned instead of null because Velocity does not like null + * when used in #set. + */ + public String genCascades(AssociationRole role) { + List<String> cascades = StringUtil.strToList(role.getCascade(), ',', true/*trim*/); + if (cascades == null) { + return ""; + } + StringBuffer buffer = new StringBuffer("{"); + for (int i = 0, n = cascades.size(); i < n; ++i) { + String cascade = (String)cascades.get(i); + String enumStr; + if (cascade.equals(TagNames.ALL_CASCADE)) { + enumStr = "CascadeType.ALL"; + } else if (cascade.equals(TagNames.PERSIST_CASCADE)) { + enumStr = "CascadeType.PERSIST"; + } else if (cascade.equals(TagNames.MERGE_CASCADE)) { + enumStr = "CascadeType.MERGE"; + } else if (cascade.equals(TagNames.REMOVE_CASCADE)) { + enumStr = "CascadeType.REMOVE"; + } else { + assert(cascade.equals(TagNames.REFRESH_CASCADE)); + enumStr = "CascadeType.REFRESH"; + } + if (i != 0) { + buffer.append(", "); + } + buffer.append(enumStr); + } + buffer.append('}'); + return buffer.toString(); + } + /** + * Returns the fetch type annotation member value, or empty string + * if none. + * Empty string is returned instead of null because Velocity does not like null + * when used in #set. + */ + public String genFetch(ORMGenTable table) { + String fetch = table.getDefaultFetch(); + if (fetch == null) { + return ""; + } else if (fetch.equals(ORMGenTable.LAZY_FETCH)) { + return "FetchType.LAZY"; + } else { + return "FetchType.EAGER"; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java new file mode 100644 index 0000000000..ce93f829e3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/DatabaseAnnotationNameBuilder.java @@ -0,0 +1,96 @@ +package org.eclipse.jpt.gen.internal2; + +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Table; + + +/** + * Provide a pluggable way to determine whether and how the entity generator + * prints the names of various database objects. + */ +public interface DatabaseAnnotationNameBuilder { + + /** + * Given the name of an entity and the table to which it is mapped, + * build and return a string to be used as the value for the entity's + * Table annotation's 'name' element. Return null if the entity + * maps to the table by default. + */ + String buildTableAnnotationName(String entityName, Table table); + + /** + * Given the name of an attribute (field or property) and the column + * to which it is mapped, + * build and return a string to be used as the value for the attribute's + * Column annotation's 'name' element. Return null if the attribute + * maps to the column by default. + */ + String buildColumnAnnotationName(String attributeName, Column column); + + /** + * Given the name of an attribute (field or property) and the + * many-to-one or many-to-many foreign key to which it is mapped, + * build and return a string to be used as the value for the attribute's + * JoinColumn annotation's 'name' element. Return null if the attribute + * maps to the join column by default. + * The specified foreign key consists of a single column pair whose + * referenced column is the single-column primary key of the foreign + * key's referenced table. + */ + String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey); + + /** + * Build and return a string to be used as the value for a JoinColumn + * annotation's 'name' or 'referencedColumnName' element. + * This is called for many-to-one and many-to-many mappings when + * the default join column name and/or referenced column name are/is + * not applicable. + * @see buildJoinColumnAnnotationName(String, ForeignKey) + */ + String buildJoinColumnAnnotationName(Column column); + + /** + * Build and return a string to be used as the value for a JoinTable + * annotation's 'name' element. + * This is called for many-to-many mappings when the default + * join table name is not applicable. + */ + String buildJoinTableAnnotationName(Table table); + + + /** + * The default implementation simple returns the database object's name, + * unaltered. + */ + final class Default implements DatabaseAnnotationNameBuilder { + public static final DatabaseAnnotationNameBuilder INSTANCE = new Default(); + public static DatabaseAnnotationNameBuilder instance() { + return INSTANCE; + } + // ensure single instance + private Default() { + super(); + } + public String buildTableAnnotationName(String entityName, Table table) { + return table.getName(); + } + public String buildColumnAnnotationName(String attributeName, Column column) { + return column.getName(); + } + public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) { + return foreignKey.getColumnPair().getBaseColumn().getName(); + } + public String buildJoinColumnAnnotationName(Column column) { + return column.getName(); + } + public String buildJoinTableAnnotationName(Table table) { + return table.getName(); + } + @Override + public String toString() { + return "DatabaseAnnotationNameBuilder.Default"; //$NON-NLS-1$ + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java new file mode 100644 index 0000000000..e9048090e9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ForeignKeyInfo.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import java.util.List; + +import org.eclipse.jpt.db.ForeignKey; + +/** + * Represents the metadata for a particular foreign key relationship + * in a relational database schema. + * <p/> + * The referrer column is one which actually contains a foreign + * key constraint, and is equivalent to the "foreign key" column. + * <p/> + * The referenced column is one which a referrer or foreign key + * column references, and is equivalent to the "primary key" column. + * + */ +public class ForeignKeyInfo +{ + private transient ForeignKey mForeignKey ; + private String mName; + private String mReferrerTableName; + private String mReferencedTableName; + private List<String> mReferrerColNames = new java.util.ArrayList<String>(); + private List<String> mReferencedColNames = new java.util.ArrayList<String>(); + + /** + * @param fk The name of the constraint backing + * this foreign key metadata instance. + */ + public ForeignKeyInfo(ForeignKey fk, String referrerTableName, String referencedTableName) { + mForeignKey = fk; + mName = fk.getName(); + mReferrerTableName = referrerTableName; + mReferencedTableName = referencedTableName; + } + /** + * Obtain the constraint name for this foreign key specification. + * The name for a Foreign Key may, as per the JDBC specification, + * be <code>null</code> where the constraint is not named. + * In addition, it may be hardly recognizable to the user, + * particularly for DB/2 constraints. + * + * @return The name of the constraint backing + * this foreign key metadata instance. + */ + public String getName() + { + return mName; + } + + public ForeignKey getForeignKey(){ + return mForeignKey; + } + /** + * Add another pair of foreign key mappings for this foreign key + * definition. + * + * @param referrerColumn The referrer column name for this mapping. + * + * @param referencedColumn The referenced column name for this mapping. + */ + public void addColumnMapping(String referrerColName, String referencedColName) { + mReferrerColNames.add(referrerColName); + mReferencedColNames.add(referencedColName); + } + /** + * Returns the referrer table name of this foreign key + * relationship. + */ + public String getReferrerTableName() { + return mReferrerTableName; + } + /** + * Returns the referrer column names for this + * foreign key. + * The size of this list is always the same as the size of + * the list retured from <code>getReferencedColumnNames</code> + */ + public List<String> getReferrerColumnNames() { + return mReferrerColNames; + } + /** + * Returns the referenced table name of this foreign key + * relationship. + */ + public String getReferencedTableName() { + return mReferencedTableName; + } + /** + * Returns the referenced column names for this + * foreign key. + * The size of this list is always the same as the size of + * the list retured from <code>getReferrerColumnNames</code> + */ + public List<String> getReferencedColumnNames() { + return mReferencedColNames; + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + public String toString() { + return "name=" + mName + + ", referrerTable=" + mReferrerTableName + + ", referencedTable=" + mReferencedTableName + + ", referrerColumns=" + mReferrerColNames + + ", referencedColumns=" + mReferencedColNames + ; + } +} + diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java new file mode 100644 index 0000000000..25fc02e674 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenMessages.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import org.eclipse.osgi.util.NLS; + +/** + * Localized messages used by Dali entity generation. + */ +class JptGenMessages { + + public static String PackageGenerator_taskName; + public static String GenScope_taskName; + public static String EntityGenerator_taskName; + public static String Templates_notFound; + public static String Error_Generating_Entities; + + private static final String BUNDLE_NAME = "jpt_gen"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptGenMessages.class; + static { + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); + } + + private JptGenMessages() { + throw new UnsupportedOperationException(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java new file mode 100644 index 0000000000..aec0b82b88 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/JptGenPlugin.java @@ -0,0 +1,24 @@ +package org.eclipse.jpt.gen.internal2; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.osgi.framework.Bundle; + +public class JptGenPlugin { + public static final String PLUGIN_ID = "org.eclipse.jpt.gen"; + public static void logException ( String msg, Throwable e ) { + Bundle bundle = Platform.getBundle(PLUGIN_ID); + ILog log = Platform.getLog(bundle); + log.log(new Status(IStatus.ERROR, PLUGIN_ID, msg, e )); + } + + public static void logException( CoreException ce ) { + IStatus status = ce.getStatus(); + Bundle bundle = Platform.getBundle(PLUGIN_ID); + ILog log = Platform.getLog(bundle); + log.log(new Status(IStatus.ERROR, PLUGIN_ID, status.getMessage(), ce)); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java new file mode 100644 index 0000000000..24d42111c3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenColumn.java @@ -0,0 +1,329 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.gen.internal2.util.StringUtil; + + +/** + * Represents the ORM generation properties for a database + * column. + * + * <p>This is designed to be created/changed by the generation wizard, + * and generated using Velocity templates. + * The modified properties (if any) are persisted/retrieved using + * <code>ORMGenCustomizer</code>. + * + */ +public class ORMGenColumn +{ + private Table mTable; + private Column mDbColumn; + private ORMGenCustomizer mCustomizer; + private static String JAVA_LANG_PACKAGE = "java.lang."; + + public ORMGenColumn(Column dbColumn, ORMGenCustomizer customizer) { + super(); + + mDbColumn = dbColumn; + mCustomizer = customizer; + mTable = dbColumn.getTable() ; + } + public ORMGenCustomizer getCustomizer() { + return mCustomizer; + } + + protected String customized(String propName) { + return getCustomizer().getProperty(propName, mTable.getName(), getName()); + } + protected boolean customizedBoolean(String propName) { + return getCustomizer().getBooleanProperty(propName, mTable.getName(), getName()); + } + protected void setCustomized(String propName, String value) { + if (value != null && value.length() == 0) { + value = null; + } + getCustomizer().setProperty(propName, value, mTable.getName(), getName()); + } + protected void setCustomizedBoolean(String propName, boolean value, boolean defaultValue) { + if (defaultValue == value) { + setCustomized(propName, null); //remove the property + } else { + getCustomizer().setBooleanProperty(propName, value, mTable.getName(), getName()); + } + } + + /** + * Returns the column name. + */ + public String getName() { + String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder(). + buildColumnAnnotationName(mDbColumn.getName(), mDbColumn); + return annotationName!=null ? annotationName : mDbColumn.getName(); + } + + public String getJoinColumnName(){ + String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder(). + buildJoinColumnAnnotationName(mDbColumn); + return annotationName!=null ? annotationName : mDbColumn.getName(); + } + + public Column getDbColumn(){ + return this.mDbColumn; + } + + /** + * Returns the generated bean property name for the given column. + * Does not return null. + */ + public String getPropertyName() { + String name = customized(PROPERTY_NAME); + if (name == null) { + name = StringUtil.columnNameToVarName(getName()); + } + return name; + } + public void setPropertyName(String name) { + if (!StringUtil.equalObjects(name, getPropertyName())) { + setCustomized(PROPERTY_NAME, name); + } + } + + /** + * Return true if the values of name element in the @Column is default + * so we can skip generating the annotation + * + * @return true + */ + public boolean isDefault(){ + return isDefaultname() && isUpdateable() && isInsertable(); + } + + /** + * Return true if the values of name element in the @Column is default + * so we can skip generating the annotation + * + * @return true + */ + public boolean isDefaultname(){ + String propName = getPropertyName(); + String dbColumnName = getName(); + return propName.equalsIgnoreCase( dbColumnName ); + } + + + /** + * Returns the column type. + * Does not return null. + */ + public String getPropertyType() { + String type = customized(PROPERTY_TYPE); + if (type == null) { + type = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn ); + } + if( type.startsWith(JAVA_LANG_PACKAGE) ){ + type = type.substring( JAVA_LANG_PACKAGE.length() ); + } + return type; + } + public void setPropertyType(String type) { + if (!StringUtil.equalObjects(type, getPropertyType())) { + setCustomized(PROPERTY_TYPE, type); + } + } + /** + * Returns true if the column type is numeric. + */ + public boolean isNumeric() { + boolean ret = this.mDbColumn.isNumeric() ; + return ret; + + } + /** + * Returns the mapping kind, one of {@link #PROPERTY_MAPPING_KIND}|{@link #ID_MAPPING_KIND} + * |{@link #VERSION_MAPPING_KIND}|{@link #TIMESTAMP_MAPPING_KIND}. + * + * This method does not return null (defaults to basic property type). + */ + public String getMappingKind() { + String kind = customized(MAPPING_KIND); + if (kind == null) { + kind = getCustomizer().getBasicMappingKind(); + + if ( this.mDbColumn.isPartOfPrimaryKey() + && DTPUtil.getPrimaryKeyColumnNames( this.mDbColumn.getTable() ).size() == 1) { + kind = getCustomizer().getIdMappingKind(); + } + } + return kind; + } + public void setMappingKind(String mappingKind) { + if (!StringUtil.equalObjects(mappingKind, getMappingKind())) { + setCustomized(MAPPING_KIND, mappingKind); + } + } + public boolean isNullable() { + return this.mDbColumn.isNullable(); + } + + public int getSize() { + if( this.mDbColumn.isNumeric()){ + return mDbColumn.getPrecision(); + } + return mDbColumn.getLength(); + } + + public int getDecimalDigits() { + if( this.mDbColumn.isNumeric() ){ + return mDbColumn.getScale(); + } + return -1; + } + + public boolean isPrimaryKey(){ + return this.mDbColumn.isPartOfPrimaryKey() ; + } + public boolean isForeignKey() { + return this.mDbColumn.isPartOfForeignKey() ; + } + public boolean isUnique() { + return this.mDbColumn.isPartOfUniqueConstraint() ; + } + public String getPropertyDescription() { + return customized(PROPERTY_DESC); + } + + public boolean isDataTypeLOB(){ + return this.mDbColumn.isLOB(); + } + + public boolean isNeedMapTemporalType(){ + String propertyType = this.getPropertyType(); + return ( propertyType.equals("java.util.Date") || propertyType.equals("java.util.Calendar") ); + } + + public String getTemporalType(){ + String defaultType = getCustomizer().getPropertyTypeFromColumn( this.mDbColumn ); + if( defaultType.equals("java.sql.Date")){ + return "DATE"; + }else if( defaultType.equals("java.sql.Time")){ + return "TIME"; + }else { + return "TIMESTAMP"; + } + } + + /** + * Returns the generated property getter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE} + * |{@link #PRIVATE_SCOPE}. + * This method never returns null (defaults to public). + */ + public String getPropertyGetScope() { + String scope = customized(PROPERTY_GET_SCOPE); + if (scope == null) { + scope = PUBLIC_SCOPE; + } + return scope; + } + public void setPropertyGetScope(String scope) { + if (!StringUtil.equalObjects(scope, getPropertyGetScope())) { + setCustomized(PROPERTY_GET_SCOPE, scope); + } + } + /** + * Returns the generated property setter scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE} + * |{@link #PRIVATE_SCOPE}. + * This method never returns null (defaults to public). + */ + public String getPropertySetScope() { + String scope = customized(PROPERTY_SET_SCOPE); + if (scope == null) { + scope = PUBLIC_SCOPE; + } + return scope; + } + public void setPropertySetScope(String scope) { + if (!StringUtil.equalObjects(scope, getPropertySetScope())) { + setCustomized(PROPERTY_SET_SCOPE, scope); + } + } + /** + * Returns the generated field member scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE} + * |{@link #PRIVATE_SCOPE}. + * This method never returns null (defaults to private). + */ + public String getFieldScope() { + String scope = customized(FIELD_SCOPE); + if (scope == null) { + scope = PRIVATE_SCOPE; + } + return scope; + } + /** + * Returns true if this column should be used in the + * <code>equals</code> method implementation. + */ + public boolean isUseInEquals() { + return customizedBoolean(USE_IN_EQUALS) || isPrimaryKey(); + } + public void setUseInEquals(boolean value) { + setCustomizedBoolean(USE_IN_EQUALS, value, false); + } + /** + * Returns true if this column should be used in the + * <code>toString</code> method implementation. + */ + public boolean isUseInToString() { + return customizedBoolean(USE_IN_TO_STRING) || isPrimaryKey(); + } + public void setUseInToString(boolean value) { + setCustomizedBoolean(USE_IN_TO_STRING, value, false); + } + public boolean isUpdateable() { + return !"false".equals(customized(UPDATEABLE)); //defaults to true + } + public void setUpdateable(boolean value) { + setCustomizedBoolean(UPDATEABLE, value, true); + } + public boolean isInsertable() { + return !"false".equals(customized(INSERTABLE)); //defaults to true + } + public void setInsertable(boolean value) { + setCustomizedBoolean(INSERTABLE, value, true); + } + public boolean isGenerated() { + return !"false".equals(customized(GENERATED)); //defaults to true + } + public void setGenerated(boolean value) { + setCustomizedBoolean(GENERATED, value, true); + } + + /*get/set and field scopes*/ + public static final String PUBLIC_SCOPE = "public"; + public static final String PROTECTED_SCOPE = "protected"; + public static final String PRIVATE_SCOPE = "private"; + + /*customization properties*/ + private static final String PROPERTY_NAME = "propertyName"; + protected static final String PROPERTY_TYPE = "propertyType"; + protected static final String MAPPING_KIND = "mappingKind"; + private static final String PROPERTY_DESC = "propertyDesc"; + private static final String PROPERTY_GET_SCOPE = "propertyGetScope"; + private static final String PROPERTY_SET_SCOPE = "propertySetScope"; + private static final String FIELD_SCOPE = "fieldScope"; + private static final String USE_IN_EQUALS = "useInEquals"; + private static final String USE_IN_TO_STRING = "useInToString"; + private static final String UPDATEABLE = "updateable"; + private static final String INSERTABLE = "insertable"; + private static final String GENERATED = "genProperty"; +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java new file mode 100644 index 0000000000..32496eb8ac --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenCustomizer.java @@ -0,0 +1,752 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.gen.internal2.util.FileUtil; +import org.eclipse.jpt.gen.internal2.util.StringUtil; + +/** + * Contains the information used to customize the database schema to ORM entity + * generation. + * + * <p>The customization settings are mainly exposed in the form of + * properties. There are no assumptions in this class about the meaning of the + * property names. Properties can be associated to specific tables and table + * columns, or globally for any table and/or column. + * + * <p>Subclass can implement the sets of abstract methods to provide ORM vendor + * specific properties. + * + */ +public abstract class ORMGenCustomizer implements java.io.Serializable +{ + private final static long serialVersionUID = 1; + + /** + * A value passed for the table name argument to get/setProperty + * indicating that the value applies to any table. + */ + public static final String ANY_TABLE = "__anyTable__"; + /*the string used in the property name in mProps to indicate + * a null table value.*/ + private static final String NULL_TABLE = ""; + /*the string used in the property name in mProps to indicate + * a null column value.*/ + private static final String NULL_COLUMN = ""; + + /*This version number is written in the header of the customization stream + * and read at de-serialization time, if it is different then the file is invalidated. + */ + private static final int FILE_VERSION = 2; + + private static final String UPDATE_CONFIG_FILE = "updateConfigFile"; + + private transient Schema mSchema; + private transient File mFile; + + private List<String> mTableNames; + /*key: table name, value: ORMGenTable object.*/ + private transient Map<String , ORMGenTable> mTables; + /*the <code>Association</code> objects sorted by their "from" + * table name. Includes all association derived from foreign keys + * in user selected tables. Since some of the foreign keys may point to table + * user does not select, this list may be different from mValidAssociations + **/ + private List<Association> mAssociations; + /* + * List of valid associations within the user selected tables + * */ + private transient List<Association> mValidAssociations; + private transient boolean mInvalidForeignAssociations; + + /*the property name is in the form $tableName.$columnName.$propertyName. + * Where tableName could be NULL_TABLE or ANY_TABLE + * and columnName could be NULL_COLUMN*/ + private Map<String, String> mProps = new java.util.HashMap<String, String>(); + + private transient DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder = DatabaseAnnotationNameBuilder.Default.INSTANCE; + + //----------------------------------------- + //---- abstract methods + //----------------------------------------- + /** + * Returns all the primary key generator schemes. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract List<String> getAllIdGenerators(); + /** + * Returns the string representing the developer-assigned id generator. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String getNoIdGenerator(); + /** + * Returns the string representing the identity id generator. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String getIdentityIdGenerator(); + /** + * Returns the strings representing the sequence generators. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract Set<String> getSequenceIdGenerators(); + /** + * Returns a property type from the given database column. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String getPropertyTypeFromColumn(Column column) ; + /** + * Returns all the strings representing property types. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String[] getAllPropertyTypes(); + /** + * Returns all the strings representing property mapping kinds. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String[] getAllMappingKinds(); + /** + * Returns the basic (default) property mapping kind. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String getBasicMappingKind(); + /** + * Returns the id (primary key) property mapping kind. + * This can return any strings as far as the Velocity template + * processor understand them. + */ + public abstract String getIdMappingKind(); + /** + * Interacts with the user to edit the cascade of the given + * role. + * This method should also call <code>AssociationRole.setCascade</code>. + * + * @return false if the user interaction is cancelled. + */ + public abstract boolean editCascade(AssociationRole role); + + //----------------------------------------- + //----------------------------------------- + + /** + * @param file The file that contains the customization settings. + * The file is created if necessary when the <code>save</code> + * method is called. + */ + public void init( File file, Schema schema) { + this.mSchema = schema; + mFile = file; + + if (!file.exists()) { + /*A hack to set the default to eager so thet app does not throw at runtime for new apps + * (in case a lazy strategy is not developed yet). This is done instead of in ORMGenTable.getDefaultFetch + * for backward compatibility.*/ + setProperty(ORMGenTable.DEFAULT_FETCH, ORMGenTable.EAGER_FETCH, ORMGenCustomizer.ANY_TABLE, null); + return; + } + InputStream istream = null; + ObjectInputStream ois = null; + try + { + //read it in a file first to speedup deserialization + byte[] bytes = FileUtil.readFile(file); + istream = new ByteArrayInputStream(bytes); + ois = new ObjectInputStream(istream); + + FileHeader header = (FileHeader)ois.readObject(); + if (header.mVersion == FILE_VERSION) { + ORMGenCustomizer customizer = (ORMGenCustomizer)ois.readObject(); + restore(customizer); + } + } catch (Exception ex) { + System.out.println("***ORMGenCustomizer.load failed "+file+": " + ex); + } + finally + { + if (ois != null) + { + try + { + ois.close(); + } catch (IOException e) { + } + } + + if (istream != null) + { + try + { + istream.close(); + } catch (IOException e) { + } + } + } + } + + public void setSchema(Schema schema){ + this.mSchema = schema; + } + + public Schema getSchema(){ + return mSchema; + } + + /** + * Empty constructor needed by the deserialization. + */ + public ORMGenCustomizer() { + super(); + } + + /** + * Saves the customization file. + * The file is created if necessary. + */ + public void save() throws IOException { + //System.out.println("---ORMGenCustomizer.save: " + mFile); + if (!mFile.exists() && !mFile.createNewFile()) { + return; + } + java.io.FileOutputStream fos = null; + java.io.ObjectOutputStream oos = null; + boolean deleteIt = true; + try { + fos = new java.io.FileOutputStream(mFile); + oos = new java.io.ObjectOutputStream(fos); + FileHeader header = new FileHeader(); + oos.writeObject(header); + oos.writeObject(this); + deleteIt = false; + } catch (Exception ex) { + //deleteIt is true, so the cache is not saved. + CoreException ce = new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, + "Unable to save the ORMGenCustomizer file: "+mFile,ex)); + JptGenPlugin.logException( ce ); + } finally { + try { + if (oos!=null) oos.close(); + if (fos!=null) fos.close(); + if (deleteIt) { + mFile.delete(); + } + } catch (java.io.IOException ex2) {} + } + } + + public DatabaseAnnotationNameBuilder getDatabaseAnnotationNameBuilder() { + return this.databaseAnnotationNameBuilder; + } + public void setDatabaseAnnotationNameBuilder(DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder) { + if (databaseAnnotationNameBuilder == null) { + throw new NullPointerException("database annotation name builder is required"); //$NON-NLS-1$ + } + this.databaseAnnotationNameBuilder = databaseAnnotationNameBuilder; + } + + /** + * Returns a property value. + */ + public String getProperty(String propertyName, String tableName, String colName) { + String key = getPropKey(propertyName, tableName, colName); + String value = (String)mProps.get(key); + /*if the key does not exist and it is a table property then + * get the default table property.*/ + if (value == null && tableName != null && colName == null && !tableName.equals(ANY_TABLE)) { + value = getProperty(propertyName, ANY_TABLE, colName); + } + return value; + } + /** + * Changes a property value. + * + * @param value The new value, could be null. + */ + public void setProperty(String propertyName, String value, String tableName, String colName) { + String key = getPropKey(propertyName, tableName, colName); + if (value != null) { + mProps.put(key, value); + } else { + mProps.remove(key); + } + } + /** + * Same as {@link #getProperty(String, String, String)} but + * converts the value to boolean. + */ + public boolean getBooleanProperty(String propertyName, String tableName, String colName) { + String value = getProperty(propertyName, tableName, colName); + return "true".equals(value); + } + /** + * Changes a table boolean property value. + */ + public void setBooleanProperty(String propertyName, boolean value, String tableName, String colName) { + setProperty(propertyName, value ? "true" : "false", tableName, colName); + } + /** + * Returns the names of the tables to generate. + */ + @SuppressWarnings("unchecked") + public List<String> getTableNames() { + return mTableNames != null ? mTableNames : java.util.Collections.EMPTY_LIST; + } + /** + * Called when the table user selection is changed in the + * generation wizard. + */ + public void setTableNames(List<String> tableNames) { + mTableNames = tableNames; + mTables = null; + mValidAssociations = null; //recompute + mInvalidForeignAssociations = true; //make sure foreign associations from newly added tables are computed. + } + /** + * Returns the table names to be generated. + * This might be different from <code>getTableNames</code> if there + * are many-to-many join tables and are not contributing + * in any other associations. + */ + public List<String> getGenTableNames() { + List<String> names = getTableNames(); + List<String> result = new java.util.ArrayList<String>(names.size()); + + /*filter out join tables*/ + List<Association> associations = getAssociations(); + for (Iterator<String> tableNamesIter = names.iterator(); tableNamesIter.hasNext(); ) { + String tableName = (String)tableNamesIter.next(); + boolean isValid = true; + + for (Iterator<Association> assocIter = associations.iterator(); assocIter.hasNext(); ) { + Association association = (Association)assocIter.next(); + if (!association.isGenerated()) { + continue; + } + if (tableName.equals(association.getReferrerTableName()) + || tableName.equals(association.getReferencedTableName())) { + isValid = true; + break; + } + if (tableName.equals(association.getJoinTableName())) { + isValid = false; + } + } + if (isValid) { + result.add(tableName); + } + } + return result; + } + /** + * Returns an <code>ORMGenTable</code> object given its name, or + * null if none. + */ + public ORMGenTable getTable(String tableName) { + if (mTables == null) { + mTables = new java.util.HashMap<String, ORMGenTable>(mTableNames.size()); + } + + if(mTableNames!=null && mSchema!=null){ + for (Iterator<String> iter = mTableNames.iterator(); iter.hasNext(); ) { + String name = (String)iter.next(); + Table dbTable = mSchema.getTableNamed( name ); + if (dbTable != null) { + mTables.put(name, createGenTable(dbTable)); + } + } + } + return (ORMGenTable)mTables.get(tableName); + } + /** + * Returns the <code>Association</code> objects sorted by their "from" + * table name. + */ + public List<Association> getAssociations(){ + return getAssociations(true/*validOnly*/); + } + /** + * Adds the given association. + */ + public void addAssociation(Association association) { + getAssociations(false/*validOnly*/).add(association); + if (mValidAssociations != null) { + mValidAssociations.add(association); + } + + } + /** + * Deletes the given association. + */ + public void deleteAssociation(Association association) { + boolean removed = getAssociations(false/*validOnly*/).remove(association); + assert(removed); + + if (mValidAssociations != null) { + removed = mValidAssociations.remove(association); + assert(removed); + } + } + /** + * Returns true if an association similar to the given association + * already exists. + * This is decided based only on the association tables and columns. + */ + public boolean similarAssociationExists(Association association) { + try { + for (Iterator<Association> iter = getAssociations(false/*validOnly*/).iterator(); iter.hasNext(); ) { + Association association2 = (Association)iter.next(); + if (!association.getReferrerTableName().equals(association2.getReferrerTableName()) + || !association.getReferencedTableName().equals(association2.getReferencedTableName()) + || !StringUtil.equalObjects(association.getJoinTableName(), association2.getJoinTableName()) + || !association.getReferrerColumnNames().equals(association2.getReferrerColumnNames()) + || !association.getReferencedColumnNames().equals(association2.getReferencedColumnNames()) + ) { + continue; + } + /*the 2 association have the same referrer, referenced and join table*/ + if (association.getJoinTableName() == null) { + return true; + } + if (association.getReferrerJoinColumnNames().equals(association2.getReferrerJoinColumnNames()) + && association.getReferencedJoinColumnNames().equals(association2.getReferencedJoinColumnNames())) { + return true; + } + } + } catch (Exception e) { + return false; + } + return false; + } + /** + * Creates the <code>ORMGenTable</code> instance. + */ + public ORMGenTable createGenTable(Table dbTable) { + return new ORMGenTable(dbTable, this); + } + /** + * Creates the <code>ORMGenColumn</code> instance. + */ + protected ORMGenColumn createGenColumn(Column dbCol) { + return new ORMGenColumn(dbCol, this); + } + /** + * Returns true of the underlying persistence specs require the "many" side + * of an association to be the owner (like EJB3). + */ + protected boolean manySideIsAssociationOwner() { + return false; + } + public boolean isUpdateConfigFile() { + return !"false".equals(getProperty(UPDATE_CONFIG_FILE, null, null)); //defaults to true + } + public void setUpdateConfigFile(boolean value) { + if (value) { //default is true + setProperty(UPDATE_CONFIG_FILE, null, null, null); //remove it + } else { + setBooleanProperty(UPDATE_CONFIG_FILE, value, null, null); + } + } + + //----------------------------------------- + //---- Velocity templates methods + //----------------------------------------- + /** + * Returns a getter method name given a property name. + */ + public String propertyGetter(String propertyName) { + return "get"+StringUtil.initUpper(propertyName); + } + /** + * Returns a setter method name given a property name. + */ + public String propertySetter(String propertyName) { + return "set"+StringUtil.initUpper(propertyName); + } + public String quote(String s) { + return StringUtil.quote(s, '"'); + } + public String quote(boolean b) { + return quote(String.valueOf(b)); + } + public String quote(int i) { + return quote(String.valueOf(i)); + } + /** + * Appends an annotation member name and value to an existing annotation. + * + * @param s The annotation members string. + * + * @param memberValue The member value, if null or empty strings then + * nothing is appened. + * + * @param whether to double quote the member value. + */ + public String appendAnnotation(String s, String memberName, String memberValue, boolean quote) { + if (memberValue == null || memberValue.length() == 0) { + return s; + } + StringBuffer buffer = new StringBuffer(s); + if (buffer.length() != 0) { + buffer.append(", "); + } + buffer.append(memberName); + buffer.append('='); + if (quote) { + buffer.append('"'); + } + buffer.append(memberValue); + if (quote) { + buffer.append('"'); + } + return buffer.toString(); + } + public boolean isJDK1_5() { + return true; + } + + //----------------------------------------- + //---- private methods + //----------------------------------------- + /** + * Restores the customization settings from the given + * (persisted) customizer. + */ + private void restore(ORMGenCustomizer customizer) { + mTableNames = customizer.mTableNames; + mAssociations = customizer.mAssociations; + mProps = customizer.mProps; + if( mSchema == null ) + return; + + /*remove invalid table names*/ + for (int i = mTableNames.size()-1; i >= 0; --i) { + String tableName = (String)mTableNames.get(i); + if (mSchema.getTableNamed( tableName) == null) { + mTableNames.remove(i); + } + } + if( mAssociations!=null ){ + /*restore the associations*/ + for (Iterator<Association> iter = mAssociations.iterator(); iter.hasNext(); ) { + Association association = (Association)iter.next(); + association.restore(this); + } + /*add the foreign keys associations just in case the tables changed since + * the last time the state was persisted. Pass checkExisting true so that the + * associations restored above are not overwritten.*/ + addForeignKeyAssociations(true/*checkExisting*/); + } + } + /** + * Returns the key in mProps corresponding to the specified + * propertyName, table and column. + */ + private String getPropKey(String propertyName, String tableName, String colName) { + if (tableName == null) { + tableName = NULL_TABLE; + } + if (colName == null) { + colName = NULL_COLUMN; + } + return tableName + '.' + colName + '.' + propertyName; + } + /** + * Returns the associations that are valid for the + * current tables. + */ + private List<Association> getAssociations(boolean validOnly){ + if (mAssociations == null) { + mAssociations = new java.util.ArrayList<Association>(); + + addForeignKeyAssociations(false/*checkExisting*/); + } else if (mInvalidForeignAssociations) { + mInvalidForeignAssociations = false; + + addForeignKeyAssociations(true/*checkExisting*/); + } + List<Association> associations; + if (validOnly) { + if (mValidAssociations == null) { + /*filter out the invalid associations*/ + mValidAssociations = new ArrayList<Association>(mAssociations.size()); + for (int i = 0, n = mAssociations.size(); i < n; ++i) { + Association association = (Association)mAssociations.get(i); + if (association.isValid()) { + mValidAssociations.add(association); + } + } + } + associations = mValidAssociations; + } else { + associations = mAssociations; + } + return associations; + } + private void addForeignKeyAssociations(boolean checkExisting) { + List<String> tableNames = getTableNames(); + for (Iterator<String> iter = tableNames.iterator(); iter.hasNext(); ) { + ORMGenTable table = getTable((String)iter.next()); + addForeignKeyAssociations(table, checkExisting); + } + } + private void addForeignKeyAssociations(ORMGenTable table, boolean checkExisting) { + if(table==null) + return; + + + List<ForeignKeyInfo> fKeys = null; + + try{ + fKeys = DTPUtil.getForeignKeys(table.getDbTable()); + }catch(Exception ise){ + //workaround Dali bug for now + return; + } + + if( fKeys.size()==0 ) + return; + + List<Association> addedAssociations = new java.util.ArrayList<Association>(); + for (Iterator<ForeignKeyInfo> iter = fKeys.iterator(); iter.hasNext(); ) { + ForeignKeyInfo fki = (ForeignKeyInfo)iter.next(); + ORMGenTable referencedTable = getTable(fki.getReferencedTableName()); + if (referencedTable == null) { + continue; + } + Association association = new Association(this, table.getName(), fki.getReferrerColumnNames() + , referencedTable.getName(), fki.getReferencedColumnNames()); + association.computeCardinality(); + //Defer the check of similarAssociationExists after computeManyToMany() + //otherwise the MTM association will not computed correctly in some cases. + //if (checkExisting && similarAssociationExists(association)) { + // continue; + //} + addedAssociations.add(association); + } + + Association m2m = computeManyToMany(table, addedAssociations); + if (m2m != null) { + /*do not generate the 2 many-to-one*/ + for (int i = 0; i < addedAssociations.size(); ++i) { + Association association = (Association)addedAssociations.get(i); + association.setGenerated(false); + } + addedAssociations.add(0, m2m); + } + //remove the association if already existing + Iterator<Association> it = addedAssociations.iterator(); + while( it.hasNext() ){ + Association newAssociation = it.next(); + for( Association association : mAssociations ){ + if( newAssociation.equals( association )){ + //If the association is existing, don't add. + //only copy the generated flag + association.setGenerated( newAssociation.isGenerated() ); + it.remove(); + } + } + } + mAssociations.addAll(addedAssociations); + } + private Association computeManyToMany(ORMGenTable table, List<Association> addedAssociations) { + /*many-to-many associations if: + * -addedAssociations contains 2 many-to-one associations to 2 different tables t1 and t2. + * -<code>table</code> contains only the primary key columns. + * -the primary key of <code>table</code> is the concatenation of its foreign + * keys to t1 and t2.*/ + + if (addedAssociations.size() != 2) { + return null; + } + + //Assume MTM table should have only two columns that are foreign keys + if( table.getColumns().size() != 2 ){ + return null; + } + + Association assoc1 = (Association)addedAssociations.get(0); + Association assoc2 = (Association)addedAssociations.get(1); + if (assoc1.getCardinality() != Association.MANY_TO_ONE + || assoc2.getCardinality() != Association.MANY_TO_ONE) { + return null; + } + ORMGenTable t1 = assoc1.getReferencedTable(); + ORMGenTable t2 = assoc2.getReferencedTable(); + +//Commented out because the assumption is too restrictive: +//this check will prevent generating table MTM to itself +// if (t1.getName().equals(t2.getName()) || +// t1.getName().equals(table.getName()) || t2.getName().equals(table.getName())) { + if( t1.getName().equals(table.getName()) || t2.getName().equals(table.getName()) ) { + return null; + } + +//Commented out because the assumption is too restrictive: +//this check will prevent generating MTM mapping table not having +//primary key defined +// List pkNames = DTPUtil.getPrimaryKeyColumnNames(table.getDbTable()); +// if (pkNames.size() != table.getColumnNames().size()) { +// return null; +// } +// List fkNames = new java.util.ArrayList(assoc1.getReferrerColumnNames()); //clone because we modify by addAll below +// fkNames.addAll(assoc2.getReferrerColumnNames()); +// if (!CollectionUtil.equalsIgnoreOrder(pkNames, fkNames)) { +// return null; +// } + Association m2m = new Association(this, t1.getName()/*referrerTableName*/, assoc1.getReferencedColumnNames()/*referrerColNames*/ + , t2.getName()/*referencedTableName*/, assoc2.getReferencedColumnNames()/*referencedColNames*/ + , table.getName(), assoc1.getReferrerColumnNames()/*referrerJoinColNames*/, assoc2.getReferrerColumnNames()/*referencedJoinColNames*/); + m2m.setCustom(false); + return m2m; + } + + //--------------------------------------------------- + //---- FileHeader class ----------------------------- + //--------------------------------------------------- + /** + * The header of the customization file. + */ + private static class FileHeader implements java.io.Serializable + { + private static final long serialVersionUID = 1L; + /** + * Should be argument-less because it is used in + * the de-serialization process. + */ + public FileHeader() { + mVersion = FILE_VERSION; + } + int mVersion; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java new file mode 100644 index 0000000000..11ab29a29a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/ORMGenTable.java @@ -0,0 +1,828 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.gen.internal2.util.StringUtil; +import org.eclipse.jpt.utility.JavaType; + +/** + * Represents the ORM generation properties for a database + * table. + * + * <p>This is designed to be created/changed by the generation wizard, + * and generated using Velocity templates. + * The modified properties (if any) are persisted/retrieved using + * <code>ORMGenCustomizer</code>. + * + */ +public class ORMGenTable +{ + private ORMGenCustomizer mCustomizer; + private List<ORMGenColumn> mColumns; + private Table mDbTable; + + /** + * @param table The database table or null if this table is used + * to get/set the default table properties (properties that apply to all tables unless overriden). + */ + public ORMGenTable(Table table, ORMGenCustomizer customizer) { + super(); + + mDbTable = table; + mCustomizer = customizer; + } + public ORMGenCustomizer getCustomizer() { + return mCustomizer; + } + /** + * Returns true if this table is is used to get/set the default + * table properties. + */ + public boolean isDefaultsTable() { + return mDbTable == null; + } + + protected String customized(String propName) { + return getCustomizer().getProperty(propName, getName(), null); + } + protected boolean customizedBoolean(String propName) { + return getCustomizer().getBooleanProperty(propName, getName(), null); + } + protected void setCustomized(String propName, String value) { + if (value != null && value.length() == 0) { + value = null; + } + getCustomizer().setProperty(propName, value, getName(), null); + } + protected void setCustomizedBoolean(String propName, boolean value, boolean defaultValue) { + if (defaultValue == value) { + setCustomized(propName, null); //remove the property + } else { + getCustomizer().setBooleanProperty(propName, value, getName(), null); + } + } + public Table getDbTable() { + return mDbTable; + } + /** + * Returns the table name. + */ + public String getName() { + if( mDbTable == null ) + return ORMGenCustomizer.ANY_TABLE; + String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder(). + buildTableAnnotationName(mDbTable.getName(), mDbTable); + return annotationName != null ? annotationName : mDbTable.getName(); + } + + public String getJoinTableAnnotationName(){ + if( mDbTable == null ) + return ORMGenCustomizer.ANY_TABLE; + String annotationName = this.mCustomizer.getDatabaseAnnotationNameBuilder(). + buildJoinTableAnnotationName( mDbTable); + return annotationName != null ? annotationName : mDbTable.getName(); + } + + /** + * Returns the database schema containing the table. + */ + public String getSchema() { + if( DTPUtil.isDefaultSchema( mDbTable )) + return ""; + String schemaName = mDbTable.getSchema().getName(); + + return schemaName; + } + /** + * Sets the package for the generated class (empty string for the default package) + */ + public void setPackage(String srcFolder, String pkg) { + setCustomized(SRC_FOLDER, srcFolder); + + getCustomizer().setProperty(PACKAGE, pkg, getName(), null); //not calling setCustomized so that empty strings do not get nulled out. + } + /** + * Returns the Java package (empty string for the default package). + */ + public String getPackage() { + return customized(PACKAGE); + } + + /** + * Returns the generated Java class name (not qualified). + */ + public String getClassName() { + String name = customized(CLASS_NAME); + if (name == null) { + name = StringUtil.tableNameToVarName(getName()); + name = StringUtil.initUpper(name); + name = StringUtil.singularise(name); + } + return name; + } + public void setClassName(String className) { + /*if the class name is the same as the (possibly computed) class name + * then nothing to do*/ + if (!StringUtil.equalObjects(className, getClassName())) { + setCustomized(CLASS_NAME, className); + } + } + /** + * Returns a name suitable to be used as a variable or class name. + * This is computed based on the table name. + * + * @param singular Whether the name should be singular or plural. + */ + public String getVarName(boolean singular) { + String name = StringUtil.tableNameToVarName(getName()); + if (singular) { + name = StringUtil.singularise(name); + } else { + name = StringUtil.pluralise(name); + } + return name; + } + /** + * Returns the fully qualified generated Java class name. + */ + public String getQualifiedClassName() { + return qualify(getClassName()); + } + /** + * Returns the composite key Java class name (not qualified). + */ + public String getCompositeKeyClassName() { + String name = customized(COMPOSITE_KEY_CLASS_NAME); + if (name == null) { + name = getClassName() + "PK"; + } + return name; + } + /** + * Returns the fully qualified composite key Java class name. + */ + public String getQualifiedCompositeKeyClassName() { + return qualify(getCompositeKeyClassName()); + } + /** + * Returns the composite key property name. + */ + public String getCompositeKeyPropertyName() { + return "compId"; + } + /** + * Returns the <code>ORMGenColumn</code> objects to be + * generated for this table. + */ + public List<ORMGenColumn> getColumns() { + if (mColumns == null) { + mColumns = new ArrayList<ORMGenColumn>(); + Iterator<Column> cols = mDbTable.columns(); + while (cols.hasNext() ) { + Column c = cols.next(); + ORMGenColumn genColumn = getCustomizer().createGenColumn( c ); + mColumns.add( genColumn ); + } + } + return mColumns; + } + public List<String> getColumnNames() { + Iterator<Column> cols = mDbTable.columns(); + List<String> ret = new ArrayList<String>(); + while (cols.hasNext() ) { + Column c = cols.next(); + ret.add(c.getName()); + } + return ret; + } + /** + * Returns the <code>ORMGenColumn</code> objects representing + * the table's primary key. + */ + public List<ORMGenColumn> getPrimaryKeyColumns() { + List<Column> dbCols = DTPUtil.getPrimaryKeyColumns( mDbTable); + List<ORMGenColumn> ret = new ArrayList<ORMGenColumn>(); + for(Column dbCol : dbCols ){ + ret.add(new ORMGenColumn(dbCol, this.mCustomizer)); + } + return ret; + } + /** + * Returns the primary key column or null if there is + * no or many primary key columns. + */ + public ORMGenColumn getPrimaryKeyColumn() { + ORMGenColumn pkCol = null; + List<ORMGenColumn> pkColumns = getPrimaryKeyColumns(); + if (pkColumns.size() == 1) { + //Column dbCol = (Column)pkColumns.get(0); + pkCol = pkColumns.get(0); //(ORMGenColumn) mCustomizer.createGenColumn(dbCol); + } else { + /*if no pk column then look for the first column with id + * mapping kind. This is so that the wizard can be used with tables + * not having primary keys. */ + List<ORMGenColumn> columns = getColumns(); + for (int i = 0, n = columns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)columns.get(i); + if (column.getMappingKind().equals(mCustomizer.getIdMappingKind())) { + pkCol = column; + break; + } + } + } + return pkCol; + } + /** + * Returns true if there is more than 1 pk column. + */ + public boolean isCompositeKey() { + return DTPUtil.getPrimaryKeyColumnNames( mDbTable ).size() > 1; + } + /** + * Returns the <code>ORMGenColumn</code> objects for the + * the columns that are not part of any association. + * + * @param genOnly Whether to include only the columns marked for generation. + * + * @param includePk Whether to include the primary kley column(s). + * + * @param includeInherited Whether to include the columns associated + * with Java properties that exist in the super class (if any). + */ + public List<ORMGenColumn> getSimpleColumns(boolean genOnly, boolean includePk, boolean includeInherited){ + List<ORMGenColumn> result = new java.util.ArrayList<ORMGenColumn>(); + + List<ORMGenColumn> columns = getColumns(); + List<AssociationRole> roles = getAssociationRoles(); + for (int i = 0, n = columns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)columns.get(i); + if (genOnly && !column.isGenerated()) { + continue; + } + if (column.isPrimaryKey()) { + if (!includePk || isCompositeKey()) { + continue; + } + } else if (isColumnInAsscociation(column, roles)) { + continue; + } + + result.add(column); + } + return result; + + } + public List<ORMGenColumn> getSimpleColumns() { + return getSimpleColumns(true/*genOnly*/, true/*includePk*/, true/*includeInherited*/); + } + /** + * Returns false if the given column should be generated with + * false updatable/insertable. + * This is the case when the column is mapped more than once, this + * usually happen with columns in composite keys and many-to-one + * associations. + * + * <br>Note that for Hibernate the column param is null because + * the insert/update attributes are specified for the many-to-one tag itself + * instead of the nested column tags (bogus obviously). + */ + public boolean isColumnUpdateInsert(AssociationRole role, ORMGenColumn column) { + if (column == null) { + for (Iterator<ORMGenColumn> iter = role.getReferrerColumns().iterator(); iter.hasNext(); ) { + ORMGenColumn c = (ORMGenColumn)iter.next(); + if (!isColumnUpdateInsert(role, c)) { + return false; + } + } + return true; + } + + if (column.isPrimaryKey()) { + return false; + } + /*should look if there are multiple associations using the same column + * and return false, but this is probably an unusual case.*/ + + return true; + } + /** + * Returns the <code>ORMGenColumn</code> objects corresponding + * to the given column names. + */ + public List<ORMGenColumn> getColumnsByNames(List<String> names){ + List<ORMGenColumn> result = new java.util.ArrayList<ORMGenColumn>(); + for( String name : names ){ + ORMGenColumn column = getColumnByName(name); + assert(column != null); + if (column != null) { + result.add(column); + } + } + return result; + } + /** + * Returns the columns having the given name, or null if none. + */ + public ORMGenColumn getColumnByName(String name) { + List<ORMGenColumn> columns = getColumns(); + for (int i = 0, n = columns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)columns.get(i); + if (column.getName().equals(name)) { + return column; + } + } + return null; + } + /** + * Returns the <code>AssociationRole</code> objects for this table. + * Only the association marked for generation are returned. + */ + public List<AssociationRole> getAssociationRoles(){ + /*this is not cached intentionally because invalidating the + * cache with wizard changes is kinda tricky.*/ + List<AssociationRole> associationRoles = new ArrayList<AssociationRole>(); + + String name = getName(); + List<Association> associations = mCustomizer.getAssociations(); + for (Iterator<Association> iter = associations.iterator(); iter.hasNext(); ) { + Association association = (Association)iter.next(); + if (!association.isGenerated()) { + continue; + } + /*check both referrer *and* referenced because an association could be + * from-to the same table (employee/manager)*/ + if (association.getReferrerTable().getName().equals(name)) { + AssociationRole role = association.getReferrerRole(); + if (role != null) { + associationRoles.add(role); + } + } + if (association.getReferencedTable().getName().equals(name)) { + AssociationRole role = association.getReferencedRole(); + if (role != null) { + associationRoles.add(role); + } + } + } + return associationRoles; + } + public String getClassDescription() { + return customized(CLASS_DESC); + } + /** + * Returns the generated class scope, one of {@link #PUBLIC_SCOPE}|{@link #PROTECTED_SCOPE} + * |{@link #PRIVATE_SCOPE}. + * This method never returns null (defaults to public). + */ + public String getClassScope() { + String scope = customized(CLASS_SCOPE); + if (scope == null) { + scope = PUBLIC_SCOPE; + } + return scope; + } + public String getExtends() { + return customized(EXTENDS); + } + public void setExtends(String baseClass) { + setCustomized(EXTENDS, baseClass); + } + public List<String> getImplements() { + String str = customized(IMPLEMENTS); + List<String> result = StringUtil.strToList(str, ',', true/*trim*/); + if (result == null) { + result = Collections.emptyList(); + } + return result; + } + public void setImplements(List<String> interfaces) { + setCustomized(IMPLEMENTS, StringUtil.listToStr(interfaces, ',')); + } + /** + * Returns the string that should be generated in the Java class + * for extends and implements. + */ + public String generateExtendsImplements() { + StringBuffer buffer = new StringBuffer(); + + String extendsClass = getExtends(); + if (extendsClass != null && !extendsClass.equals("java.lang.Object") && !extendsClass.equals("Object")) { + buffer.append("extends " + simplifyClassName(extendsClass)); + } + + buffer.append(" implements Serializable"); //assuming that the Java file template imports the java.io.Serializable + + for (Iterator<String> iter = getImplements().iterator(); iter.hasNext(); ) { + buffer.append(", " + simplifyClassName((String)iter.next())); + } + + return buffer.toString(); + } + private String simplifyClassName(String fullClassName) { + final String JAVA_LANG = "java.lang."; + if (fullClassName.startsWith(JAVA_LANG)) { + return fullClassName.substring(JAVA_LANG.length()); + } + String pkg = StringUtil.getPackageName(fullClassName); + if (pkg != null && StringUtil.equalObjects(pkg, getPackage())) { + return StringUtil.getClassName(fullClassName); + } + return fullClassName; + } + /** + * Returns the id generator scheme (assigned, sequence, etc). + * Does not return null, defaults to "assigned" or "identity" depending on whether + * the table has an identity column. + */ + public String getIdGenerator() { + String generator = customized(ID_GENERATOR); + String noneGenerator = getCustomizer().getNoIdGenerator(); + if (!isDefaultsTable()) { + /*This is done mainly because there might be cases where some tables have autoinctement pk + * and others are assigned. In this case this makes it so that it is possible to have + * a "none" default value that is interpreted depending on the case. */ + if (generator == null || generator.equals(noneGenerator)) { + ORMGenColumn pkColumn = getPrimaryKeyColumn(); + if (pkColumn != null && DTPUtil.isAutoIncrement( pkColumn.getDbColumn() )) { + generator = getCustomizer().getIdentityIdGenerator(); + } + } + } + if (generator == null) { + generator = noneGenerator; + } + return generator; + } + /** + * Changes the id generator scheme (assigned, sequence, etc). + */ + public void setIdGenerator(String scheme) { + setCustomized(ID_GENERATOR, scheme); + } + /** + * Returns the sequence name for the given table, or null if none (makes + * sense only when the scheme is native, sequence, ..). + */ + public String getSequence() { + return customized(SEQUENCE); + } + public void setSeqence(String name) { + setCustomized(SEQUENCE, name); + } + /** + * Returns the sequence name after replacing the ${table} and ${pk} + * by their values, or null if none. + */ + public String getFormattedSequence() { + String sequence = getSequence(); + if (sequence != null) { + /*resolve the ${table} and ${pk} patterns*/ + sequence = StringUtil.strReplace(sequence, TABLE_SEQ_PATTERN, getName()); + + if (sequence.indexOf(PK_SEQ_PATTERN) >= 0) { + List<String> pkNames = DTPUtil.getPrimaryKeyColumnNames( getDbTable() ); + String pkName = null; + if (pkNames.size()>0 ) { + pkName = (String)pkNames.get(0); + } + sequence = StringUtil.strReplace(sequence, PK_SEQ_PATTERN, pkName); + } + } + return sequence!=null?sequence.toUpperCase():""; + } + public boolean isImplementEquals() { + return !"true".equals(customized(IMPLEMENT_EQUALS)); //defaults to false + } + public void setImplementEquals(boolean value) { + setCustomizedBoolean(IMPLEMENT_EQUALS, value, true); + } + + /** + * Returns true if there is any column participating in equals/hashcode. + */ + public boolean hasColumnsInEquals() { + List<ORMGenColumn> columns = getSimpleColumns(); + for (int i = 0, n = columns.size(); i < n; ++i) { + ORMGenColumn column = (ORMGenColumn)columns.get(i); + if (column.isUseInEquals()) { + return true; + } + } + return false; + } + + /** + * Returns {@link #GENERATE_DDL_ANNOTATION} indicating whether + * the optional DDL parameters like length, nullable, unqiue, etc should be generated + * in @Column annotation. + * defaults to false. + */ + public boolean isGenerateDDLAnnotations() { + return "true".equals(customized(GENERATE_DDL_ANNOTATION)); //defaults to false + } + + public void setGenerateDDLAnnotations(boolean generate) { + setCustomizedBoolean(GENERATE_DDL_ANNOTATION, generate, false); + } + + /** + * Returns one of {@link #PROPERTY_ACCESS}|{@link #FIELD_ACCESS} indicating how + * the entity properties are mapped. + * Does not return null (defaults to {@link #FIELD_ACCESS}). + */ + public String getAccess() { + String name = customized(ACCESS); + if (name == null) { + name = FIELD_ACCESS; + } + return name; + } + public void setAccess(String access) { + assert(access == null || access.equals(PROPERTY_ACCESS) || access.equals(FIELD_ACCESS)); + if (!StringUtil.equalObjects(access, getAccess())) { + setCustomized(ACCESS, access); + } + } + /** + * Returns one of {@link #LAZY_FETCH}|{@link #EAGER_FETCH} indicating how + * the table associations are feched. + * Returns null if the provider defaults should be used. + */ + public String getDefaultFetch() { + return customized(DEFAULT_FETCH); + } + public void setDefaultFetch(String fetch) { + assert(fetch == null || fetch.equals(LAZY_FETCH) || fetch.equals(EAGER_FETCH)); + setCustomized(DEFAULT_FETCH, fetch); + } + public String[] getSupportedCollectionTypes() { + return new String[] {SET_COLLECTION_TYPE, LIST_COLLECTION_TYPE}; + } + /** + * Returns one of {@link #LIST_COLLECTION_TYPE}|{@link #SET_COLLECTION_TYPE} indicating + * the Java type (full class name) used for properties of collection types. + * This does not return null (defaults to list). + */ + public String getDefaultCollectionType() { + String cType = customized(DEFAULT_COLLECTION_TYPE); + if (cType == null) { + cType = SET_COLLECTION_TYPE; + } + return cType; + } + public void setDefaultCollectionType(String cType) { + assert(cType.equals(LIST_COLLECTION_TYPE) || cType.equals(SET_COLLECTION_TYPE)); + setCustomized(DEFAULT_COLLECTION_TYPE, cType); + } + /** + * Returns true if the primary key is compound and any of its + * columns should be included in the <code>equals</code> method + * implementation. + */ + public boolean isCompoundKeyUseInEquals() { + if (isCompositeKey()) { + for (Iterator<ORMGenColumn> iter = getPrimaryKeyColumns().iterator(); iter.hasNext();) { + ORMGenColumn column = (ORMGenColumn) iter.next(); + if (column.isUseInEquals()) { + return true; + } + } + } + return false; + } + public boolean isRoleUseInEquals(AssociationRole role) { + for (Iterator<ORMGenColumn> iter = role.getReferrerColumns().iterator(); iter.hasNext();) { + ORMGenColumn column = (ORMGenColumn) iter.next(); + if (column.isUseInEquals()) { + return true; + } + } + return false; + } + + + /** + * Return true if the values of name element in the @Table is default + * so we can skip generating the annotation + * + * @return true + */ + public boolean isDefaultname(){ + String className = this.getClassName(); + String tableName = this.getDbTable().getName(); + return className.equalsIgnoreCase( tableName) ; + } + + /** + * Qualifies a class name if there is a package. + */ + private String qualify(String className) { + String pkg = getPackage(); + if (pkg != null && pkg.length() != 0) { + className = pkg + '.' + className; + } + return className; + } + /** + * Returns true if the given column is part of any association. + */ + private boolean isColumnInAsscociation(ORMGenColumn column, List<AssociationRole> roles) { + for (int i = 0, n = roles.size(); i < n; ++i) { + AssociationRole role = (AssociationRole)roles.get(i); + List<ORMGenColumn> cols = role.getReferrerColumns(); + for( ORMGenColumn col : cols ){ + if (col.getName().equals( column.getName() )) { + return true; + } + } + } + return false; + } + + /** + * Print the clause to be used in the generated equals() method + * @return String + */ + public String getPrimaryKeyEqualsClause() { + StringBuilder buf = new StringBuilder(); + Iterator<ORMGenColumn> columns = this.getPrimaryKeyColumns().iterator(); + while (columns.hasNext()) { + this.printPrimaryKeyEqualsClauseOn(columns.next(), buf); + if (columns.hasNext()) { + buf.append("\n"); + buf.append("\t\t\t"); + buf.append("&& "); + } + } + buf.append(";"); + return buf.toString(); + } + + private void printPrimaryKeyEqualsClauseOn(ORMGenColumn column, StringBuilder buf) { + String fieldName = column.getPropertyName(); + JavaType javaType = column.getDbColumn().getPrimaryKeyJavaType(); + if (javaType.isPrimitive()) { + this.printPrimitiveEqualsClauseOn(fieldName, buf); + } else { + this.printReferenceEqualsClauseOn(fieldName, buf); + } + } + + private void printPrimitiveEqualsClauseOn(String fieldName, StringBuilder buf) { + buf.append("(this."); + buf.append(fieldName); + buf.append(" == castOther."); + buf.append(fieldName); + buf.append(')'); + } + + private void printReferenceEqualsClauseOn(String fieldName, StringBuilder buf) { + buf.append("this."); + buf.append(fieldName); + buf.append(".equals(castOther."); + buf.append(fieldName); + buf.append(')'); + } + + /** + * Print the clause to be used in the generated hasCode() method + * @return String + */ + public String getPrimaryKeyHashCodeClause() { + StringBuilder buf = new StringBuilder(); + Iterator<ORMGenColumn> columns = this.getPrimaryKeyColumns().iterator(); + while (columns.hasNext()) { + buf.append("hash = hash * prime + "); + this.printPrimaryKeyHashCodeClauseOn(columns.next(), buf); + buf.append(';'); + buf.append('\n'); + buf.append("\t\t"); + } + return buf.toString(); + } + + private void printPrimaryKeyHashCodeClauseOn(ORMGenColumn column, StringBuilder buf) { + String fieldName = column.getPropertyName(); + JavaType javaType = column.getDbColumn().getPrimaryKeyJavaType(); + if (javaType.isPrimitive()) { + this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, buf); + } else { + this.printReferenceHashCodeClauseOn(fieldName, buf); + } + } + + private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, StringBuilder buf) { + if (primitiveName.equals("int")) { + // this.value + buf.append("this."); + buf.append(fieldName); + } else if (primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) { // explicit cast + // ((int) this.value) + buf.append("((int) this."); + buf.append(fieldName); + buf.append(')'); + } else if (primitiveName.equals("long")) { // cribbed from Long#hashCode() + // ((int) (this.value ^ (this.value >>> 32))) + buf.append("((int) (this."); + buf.append(fieldName); + buf.append(" ^ (this."); + buf.append(fieldName); + buf.append(" >>> 32)))"); + } else if (primitiveName.equals("float")) { // cribbed from Float#hashCode() + // java.lang.Float.floatToIntBits(this.value) + buf.append("java.lang.Float"); + buf.append(".floatToIntBits(this."); + buf.append(fieldName); + buf.append(')'); + } else if (primitiveName.equals("double")) { // cribbed from Double#hashCode() + // ((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32))) + buf.append("((int) ("); + buf.append("java.lang.Double"); + buf.append(".doubleToLongBits(this."); + buf.append(fieldName); + buf.append(") ^ ("); + buf.append("java.lang.Double"); + buf.append(".doubleToLongBits(this."); + buf.append(fieldName); + buf.append(") >>> 32)))"); + } else if (primitiveName.equals("boolean")) { + // (this.value ? 1 : 0) + buf.append("(this."); + buf.append(fieldName); + buf.append(" ? 1 : 0)"); + } else { + throw new IllegalArgumentException(primitiveName); + } + } + + private void printReferenceHashCodeClauseOn(String fieldName, StringBuilder buf) { + buf.append("this."); + buf.append(fieldName); + buf.append(".hashCode()"); + } + + public String toString(){ + return "name="+ this.getName() + "; columns=" + Arrays.toString( this.getColumnNames().toArray()) ; + } + + /*class scopes*/ + public static final String PUBLIC_SCOPE = "public"; + public static final String PROTECTED_SCOPE = "protected"; + public static final String PRIVATE_SCOPE = "private"; + + /*access constants. Note that these strings are used in the ui*/ + public static final String PROPERTY_ACCESS = "property"; + public static final String FIELD_ACCESS = "field"; + + /*default fech constants. Note that these strings are used in the gen velocity templates.*/ + public static final String LAZY_FETCH = "lazy"; + public static final String EAGER_FETCH = "eager"; + + /*default collection type constants. Note that these strings are used in the gen velocity templates.*/ + public static final String LIST_COLLECTION_TYPE = "java.util.List"; + public static final String SET_COLLECTION_TYPE = "java.util.Set"; + + /** + * The pattern replaced by the table name in the id generator + * sequence name param. + */ + public static final String TABLE_SEQ_PATTERN = "$table"; + /** + * The pattern replaced by the primary key in the id generator + * sequence name param. + */ + public static final String PK_SEQ_PATTERN = "$pk"; + + /*customization properties*/ + private static final String PACKAGE = "package"; + private static final String SRC_FOLDER = "srcFolder"; + private static final String CLASS_NAME = "className"; + private static final String CLASS_DESC = "classDesc"; + private static final String CLASS_SCOPE = "classScope"; + private static final String EXTENDS = "extends"; + private static final String IMPLEMENTS = "implements"; + private static final String ID_GENERATOR = "idGenerator"; + private static final String SEQUENCE = "sequence"; + private static final String COMPOSITE_KEY_CLASS_NAME = "compositeKeyClassName"; + private static final String IMPLEMENT_EQUALS = "implementEquals"; + private static final String GENERATE_DDL_ANNOTATION = "generateDDLAnnotations"; + private static final String ACCESS = "access"; + static final String DEFAULT_FETCH = "defaultFetch"; + private static final String DEFAULT_COLLECTION_TYPE = "defaultCollectionType"; + +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java new file mode 100644 index 0000000000..105174c4d7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/OverwriteConfirmer.java @@ -0,0 +1,50 @@ +package org.eclipse.jpt.gen.internal2; + +public interface OverwriteConfirmer { + /** + * Return whether the entity generator should overwrite the specified + * file. + */ + boolean overwrite(String className); + + + final class Always implements OverwriteConfirmer { + public static final OverwriteConfirmer INSTANCE = new Always(); + public static OverwriteConfirmer instance() { + return INSTANCE; + } + // ensure single instance + private Always() { + super(); + } + // everything will be overwritten + public boolean overwrite(String arg0) { + return true; + } + @Override + public String toString() { + return "OverwriteConfirmer.Always"; //$NON-NLS-1$ + } + } + + + final class Never implements OverwriteConfirmer { + public static final OverwriteConfirmer INSTANCE = new Never(); + public static OverwriteConfirmer instance() { + return INSTANCE; + } + // ensure single instance + private Never() { + super(); + } + // nothing will be overwritten + public boolean overwrite(String arg0) { + return false; + } + @Override + public String toString() { + return "OverwriteConfirmer.Never"; //$NON-NLS-1$ + } + } + +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java new file mode 100644 index 0000000000..3b85b09fd0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/PackageGenerator2.java @@ -0,0 +1,266 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.gen.internal2; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URL; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jpt.gen.internal2.util.CompilationUnitModifier; +import org.eclipse.jpt.gen.internal2.util.FileUtil; +import org.eclipse.jpt.gen.internal2.util.UrlUtil; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; + +/** + * This generator will generate a package of entities for a set of tables. + */ +public class PackageGenerator2 { + + private IJavaProject javaProject; + private ORMGenCustomizer customizer ; + + /** + * @param customizer + * @param synchronizePersistenceXml + * @param copyJdbcDrive + * @throws Exception + */ + static public void generate(IJavaProject jpaProject, ORMGenCustomizer customizer, IProgressMonitor monitor ) throws CoreException { + PackageGenerator2 generator = new PackageGenerator2(); + generator.setProject(jpaProject); + generator.setCustomizer(customizer); + + try { + generator.doGenerate( monitor); + } catch (Exception e) { + throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Error_Generating_Entities, e)); + } + } + + private Object getCustomizer() { + return this.customizer; + } + + private void setCustomizer(ORMGenCustomizer customizer2) { + this.customizer = customizer2; + } + + private void setProject(IJavaProject proj ){ + this.javaProject = proj; + } + + protected void doGenerate( IProgressMonitor monitor ) throws Exception { + generateInternal( monitor ); + } + + protected void generateInternal( IProgressMonitor progress) throws Exception { + File templDir = prepareTemplatesFolder(); + + List<String> genClasses = new java.util.ArrayList<String>(); + List<String> tableNames = customizer.getGenTableNames(); + + /* .java per table, persistence.xml, refresh package folder */ + String taskName = NLS.bind(JptGenMessages.EntityGenerator_taskName, "Total "+ tableNames.size() + 2);//$NON-NLS-1$ + progress.beginTask(taskName, tableNames.size() + 2); + + + for (Iterator<String> iter = tableNames.iterator(); iter.hasNext();) { + String tableName = (String) iter.next(); + ORMGenTable table = (ORMGenTable) customizer.getTable(tableName); + + generateClass(table, templDir.getAbsolutePath(), progress); + progress.worked(1); + + genClasses.add(table.getQualifiedClassName()); + /* + * add the composite key class to persistence.xml because some + * JPA provider(e.g. Kodo) requires it. Hibernate doesn't seem to care). + */ + if (table.isCompositeKey()) { + genClasses.add(table.getQualifiedCompositeKeyClassName()); + } + } + progress.done(); + } + + private File prepareTemplatesFolder() throws IOException, Exception, + CoreException { + //Prepare the Velocity template folder: + //If the plug-in is packaged as a JAR, we need extract the template + //folder into the plug-in state location. This is required by Velocity + //since we use included templates. + Bundle bundle = Platform.getBundle(JptGenPlugin.PLUGIN_ID); + String templatesPath = "templates/entities/"; //$NON-NLS-1$ + Path path = new Path( templatesPath); + URL url = FileLocator.find(bundle, path, null); + if ( url ==null ) { + throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Templates_notFound + " "+ JptGenPlugin.PLUGIN_ID + "/" + templatesPath) );//$NON-NLS-1$ + } + URL templUrl = FileLocator.resolve(url); + + //Have this check so that the code would work in both PDE and JARed plug-in at runtime + File templDir = null; + if( UrlUtil.isJarUrl(templUrl) ){ + templDir = FileUtil.extractFilesFromBundle( templUrl, bundle, templatesPath ); + }else{ + templDir = UrlUtil.getUrlFile(templUrl); + } + + + if (templDir==null || !templDir.exists()) { + throw new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Templates_notFound + " "+ JptGenPlugin.PLUGIN_ID ) );//$NON-NLS-1$ + } + return templDir; + } + + /** + * Saves/Creates the .java file corresponding to a database table + * with the given content. + * + * @param templDir The velocity template file directory. It is assumed + * that this directory contains the 2 files <em>main.java.vm</em> + * and <em>pk.java.vm</em> + * @param progress + */ + protected void generateClass(ORMGenTable table, String templateDirPath, IProgressMonitor monitor) throws Exception { + + String subTaskName = NLS.bind(JptGenMessages.EntityGenerator_taskName, table.getName()); + SubMonitor sm = SubMonitor.convert(monitor, subTaskName, 100); + + try{ + IFolder javaPackageFolder = getJavaPackageFolder(table, monitor); + IFile javaFile = javaPackageFolder.getFile( table.getClassName() + ".java"); //$NON-NLS-1$ + + Properties vep = new Properties(); + vep.setProperty("file.resource.loader.path", templateDirPath); //$NON-NLS-1$ + VelocityEngine ve = new VelocityEngine(); + ve.init(vep); + sm.worked(20); + + generateJavaFile(table, javaFile, ve, "main.java.vm", true/*isDomainClass*/, monitor); //$NON-NLS-1$ + sm.worked(80); + + if (table.isCompositeKey()) { + IFile compositeKeyFile = javaPackageFolder.getFile( table.getCompositeKeyClassName()+".java"); //$NON-NLS-1$ + generateJavaFile(table, compositeKeyFile, ve, "pk.java.vm", false/*isDomainClass*/, monitor ); //$NON-NLS-1$ + } + + javaFile.refreshLocal(1, new NullProgressMonitor()); + + } catch(Throwable e){ + CoreException ce = new CoreException(new Status(IStatus.ERROR, JptGenPlugin.PLUGIN_ID, JptGenMessages.Templates_notFound + "" + JptGenPlugin.PLUGIN_ID , e) );//$NON-NLS-1$ + JptGenPlugin.logException( ce ); + } + sm.setWorkRemaining(0); + } + + private void generateJavaFile(ORMGenTable table, IFile javaFile, VelocityEngine ve + , String templateName, boolean isDomainClass, IProgressMonitor monitor) throws Exception { + VelocityContext context = new VelocityContext(); + context.put("table", table); //$NON-NLS-1$ + context.put("customizer", getCustomizer()); //$NON-NLS-1$ + + StringWriter w = new StringWriter(); + ve.mergeTemplate(templateName, context, w); + + String fileContent = w.toString(); + if (javaFile.exists()) { + if (isDomainClass) { + updateExistingDomainClass(table.getQualifiedClassName(), javaFile, fileContent); + } else { + javaFile.setContents(new ByteArrayInputStream(fileContent.getBytes()), true, true, monitor ); + } + } else { + createFile(javaFile, new ByteArrayInputStream(fileContent.getBytes())); + } + } + + + /** + * Updates the (existing) Java file corresponding to the given class. + * + * @param className The qualified class name. + * + * @param javaFile The existing Java file of the class to update. + * + * @param fileContent The new file content. + */ + protected void updateExistingDomainClass(String className, IFile javaFile, String fileContent) throws Exception { + /*use CompilationUnitModifier instead of calling WideEnv.getEnv().setFileContent + * so that if the unit is up to date if it is used before file change + * notifications are delivered (see EJB3ImportSchemaWizard.updateExistingDomainClass for example)*/ + IJavaProject project = javaProject.getJavaProject(); + CompilationUnitModifier modifier = new CompilationUnitModifier(project, className); + modifier.setJavaSource(fileContent); + modifier.save(); + } + + public void createFile(IFile file, java.io.InputStream contents) throws CoreException { + file.create(contents, false, null/*monitor*/); + } + + public IFolder getJavaPackageFolder(ORMGenTable table, IProgressMonitor monitor) throws CoreException { + IPackageFragmentRoot root = getDefaultJavaSrouceLocation ( javaProject ) ; + String packageName = table.getPackage(); + if( packageName==null ) packageName =""; + IPackageFragment packageFragment = root.getPackageFragment(packageName); + if( !packageFragment.exists()){ + root.createPackageFragment(packageName, true, monitor); + } + return (IFolder)packageFragment.getResource(); + } + + private IPackageFragmentRoot getDefaultJavaSrouceLocation(IJavaProject jproject){ + if (jproject != null) { + try { + if (jproject.exists()) { + IPackageFragmentRoot[] roots = jproject.getPackageFragmentRoots(); + for (int i= 0; i < roots.length; i++) { + if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) { + return roots[i] ; + } + } + } + } catch (JavaModelException e) { + JptGenPlugin.logException(e); + } + } + return null; + } + + + // ********** annotation name builder ********** + + +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java new file mode 100644 index 0000000000..92a60fed77 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/TagNames.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2; + +/** + * TODO: merge with JPA class ? + * The JPA mapping tag and attribute names. + * + */ +public class TagNames +{ + public static final String BASIC_TAG = "basic"; + public static final String CASCADE_TAG = "cascade"; + public static final String COLUMN_TAG = "column"; + public static final String EMBEDDED_TAG = "embedded"; + public static final String EMBEDDED_ID_TAG = "embedded-id"; + public static final String GENERATED_VALUE_TAG = "generated-value"; + public static final String ID_TAG = "id"; + public static final String ID_CLASS_TAG = "id"; + public static final String JOIN_COLUMN_TAG = "join-column"; + public static final String INVERSE_JOIN_COLUMN_TAG = "inverse-join-column"; + public static final String LOB_TAG = "lob"; + public static final String MANY_TO_MANY_TAG = "many-to-many"; + public static final String MANY_TO_ONE_TAG = "many-to-one"; + public static final String MAPPED_BY_TAG = "mapped-by"; + public static final String ONE_TO_MANY_TAG = "one-to-many"; + public static final String ONE_TO_ONE_TAG = "one-to-one"; + public static final String PK_JOIN_COLUMN_TAG = "primary-key-join-column"; + public static final String TABLE_TAG = "table"; + public static final String VERSION_TAG = "version"; + public static final String JOIN_TABLE_TAG = "join-table"; + + /*cascade tags*/ + public static final String ALL_CASCADE = "all"; + public static final String PERSIST_CASCADE = "persist"; + public static final String MERGE_CASCADE = "merge"; + public static final String REMOVE_CASCADE = "remove"; + public static final String REFRESH_CASCADE = "refresh"; +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java new file mode 100644 index 0000000000..a238b7910e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/CompilationUnitModifier.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2.util; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jface.text.Document; +import org.eclipse.text.edits.TextEdit; + + +/** + * Performs the grunt work needed for modifying a compilation + * unit and performs the modified compilation unit save. + * + * The typical usage is as follows: + * <ol><li>Create an instance. + * + * <li>Modify the compilation unit using AST operations performed + * on the node returned by {@link #getCompilationUnitNode()}. + * Alternatively you can call <code>setJavaSource</code> to change the entire source code. + * + * <li>Call the {@link #save()} method. + * + */ +public class CompilationUnitModifier +{ + private IJavaProject mProject; + private ICompilationUnit mCompilationUnit; + private CompilationUnit mCompilationUnitNode; + private Document mDocument; + + public CompilationUnitModifier(IJavaProject project, String className) throws Exception { + super(); + + mProject = project; + + IType type = project.findType(className); + if (type == null) { + throw new Exception("The class " + className + " does not exist."); + } + mCompilationUnit = type.getCompilationUnit(); + if (mCompilationUnit == null) { + throw new Exception("The source code for " + className + " does not exist."); + } + } + public CompilationUnitModifier(IJavaProject project, ICompilationUnit cu) throws Exception { + super(); + + mProject = project; + mCompilationUnit = cu; + } + public CompilationUnitModifier(IJavaProject project, ICompilationUnit cu, CompilationUnit cuNode) throws Exception { + super(); + + mProject = project; + mCompilationUnit = cu; + mCompilationUnitNode = cuNode; + + getCompilationUnitNode(); //to create mDocument (the caller in this case does not have to call getCompilationUnitNode) + } + public ICompilationUnit getCompilationUnit() { + return mCompilationUnit; + } + /** + * Returns the compilation unit node that should be used for + * tyhe modification AST operations. + */ + public CompilationUnit getCompilationUnitNode() { + if (mCompilationUnitNode == null) { + ASTParser c = ASTParser.newParser(AST.JLS3); + c.setSource(mCompilationUnit); + c.setResolveBindings(true); + mCompilationUnitNode = (CompilationUnit)c.createAST(null); + } + if (mDocument == null) { + try { + mDocument = new Document(mCompilationUnit.getBuffer().getContents()); + } catch (JavaModelException e) { + e.printStackTrace(); + } + + mCompilationUnitNode.recordModifications(); + } + + return mCompilationUnitNode; + } + /** + * Changes the entire Java source code of the compilation unit. + */ + public void setJavaSource(String newSource) { + try { + mCompilationUnit.getBuffer().setContents(newSource); + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + /** + * Saves the compilation unit modifications. + */ + public void save() throws Exception { + if (mCompilationUnitNode != null) { + assert(mDocument != null); //see getCompilationUnitNode + + //computation of the text edits + TextEdit edits = mCompilationUnitNode.rewrite(mDocument, mProject.getOptions(true)); + //computation of the new source code + edits.apply(mDocument); + String newSource = mDocument.get(); + // update of the compilation unit + mCompilationUnit.getBuffer().setContents(newSource); + } + + if (mCompilationUnit.isWorkingCopy()) { + mCompilationUnit.commitWorkingCopy(true/*force*/, null/*monitor*/); + } else { + mCompilationUnit.save(null/*monitor*/, true/*force*/); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java new file mode 100644 index 0000000000..dcf3ef9b1a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/DTPUtil.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.db.ForeignKey.ColumnPair; +import org.eclipse.jpt.gen.internal2.ForeignKeyInfo; + +/** + * Collection of utility methods to access DTP and other jpt.db APIs + * + */ +public class DTPUtil { + + /** + * Return list of the pk names + * @param dbTable + * @return + */ + public static List<String> getPrimaryKeyColumnNames(Table dbTable ) { + Iterator<Column> pkColumns = dbTable.primaryKeyColumns(); + ArrayList<String> ret = new ArrayList<String>(); + while( pkColumns.hasNext() ){ + ret.add( pkColumns.next().getName() ); + } + return ret; + } + + /** + * + * @param dbTable + * @return + */ + public static List<Column> getPrimaryKeyColumns(Table dbTable ) { + Iterator<Column> pkColumns = dbTable.primaryKeyColumns(); + ArrayList<Column> ret = new ArrayList<Column>(); + while( pkColumns.hasNext() ){ + ret.add( pkColumns.next() ); + } + return ret; + } + + public static boolean isAutoIncrement(Column c){ + //@ TODO + //Blocked by DTP bug + //https://bugs.eclipse.org/bugs/show_bug.cgi?id=250023 + //The Dali bug is + //https://bugs.eclipse.org/bugs/show_bug.cgi?id=249658 + // + return false; + } + + /** + * Return list of fk + * @param dbTable + * @return + */ + public static List<ForeignKeyInfo> getForeignKeys(Table dbTable) { + List<ForeignKeyInfo> ret = new ArrayList<ForeignKeyInfo>(); + if(dbTable!=null){ + Iterator<ForeignKey> fks = dbTable.foreignKeys(); + while( fks.hasNext() ){ + ForeignKey fk = fks.next(); + ColumnPair columnPair = fk.getColumnPair(); + + String tableName = dbTable.getName(); + String referencedTableName = ""; + Table referencedTable = fk.getReferencedTable(); + referencedTableName = referencedTable.getName(); + ForeignKeyInfo fkInfo = new ForeignKeyInfo(fk, tableName, referencedTableName ); + String baseColName = columnPair.getBaseColumn().getName(); + String referencedColName = columnPair.getReferencedColumn().getName(); + fkInfo.addColumnMapping( baseColName, referencedColName ); + ret.add( fkInfo ); + } + } + return ret; + } + + public static String getJavaType(Schema schema, Column dbColumn) { + if( isPrimaryKey(dbColumn) ) + return dbColumn.getPrimaryKeyJavaTypeDeclaration(); + return dbColumn.getJavaTypeDeclaration(); + } + + public static boolean isPrimaryKey(Column dbColumn){ + Table dbTable = dbColumn.getTable(); + Iterator<Column> pkColumns = dbTable.primaryKeyColumns(); + while( pkColumns.hasNext() ){ + if( pkColumns.next().equals( dbColumn )){ + return true; + } + } + return false; + } + + public static boolean isDefaultSchema(Table dbTable){ + String schemaName = dbTable.getSchema().getName(); + Schema defaultSchema = dbTable.getSchema().getConnectionProfile().getDatabase().getDefaultSchema(); + return defaultSchema.getName() == schemaName; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java new file mode 100644 index 0000000000..1235d6adf5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/FileUtil.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.osgi.service.datalocation.Location; +import org.osgi.framework.Bundle; + +/** + * Collections of utility methods handling files. + * + */ +public class FileUtil +{ + + private static String DELETE_FOLDER_ERR = "The directory %s could not be deleted."; + private static String DELETE_FILE_ERR = "The file %s could not be deleted."; + private static String FILE_READONLY_ERR = "The file %s could not be modified because write access is denied.\nPlease make sure that the file is not marked as readonly in the file system."; + + public static void deleteFolder(File folder) + throws IOException + { + File[] files = folder.listFiles(); + //empty the folder first (java.io.file.delete requires it empty) + if (files != null) { + for (int i = 0; i < files.length; ++i) { + File f = files[i]; + if (f.isDirectory()) + deleteFolder(f); + else + deletePath(f); + } + } + deletePath(folder); + } + + public static void deletePath(File f) + throws IOException + { + if (!f.delete()) { + String msgId = f.isDirectory() ? DELETE_FOLDER_ERR : DELETE_FILE_ERR; + throw new IOException( String.format(msgId,f.getPath())); + } + } + + public static byte[] readFile(File src) + throws IOException + { + java.io.FileInputStream fin = new java.io.FileInputStream(src); + try { + long fileLen = src.length(); + if (fileLen > Integer.MAX_VALUE) + throw new IOException("file length too big to be read by FileUtil.readFile: " + fileLen); + + byte[] bytes = new byte[(int)fileLen]; + fin.read(bytes); + return bytes; + } + finally { + fin.close(); + } + } + + public static void writeFile(File dest, byte[] bytes) + throws IOException + { + if (dest.exists() && !dest.canWrite()) + throw new IOException( FILE_READONLY_ERR ); //throw with a clear error because otherwise FileOutputStream throws FileNotFoundException! + java.io.FileOutputStream fout = new java.io.FileOutputStream(dest.getPath(), false/*append*/); + try { + fout.write(bytes); + } + finally { + fout.flush(); + fout.close(); + } + } + + /** + * Returns the url for a file. + * This basically the same as file.toUrl() but without the non-sense exception. + */ + public static URL getFileUrl(File file) { + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + return null; //should not happen as file.toURL() does not really throw an exception + } + } + + public static void setFileContent(File file, java.io.InputStream contents) throws java.io.IOException { + Path path = new Path(file.getAbsolutePath()); + try { + IFile iFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(path); + if (iFile == null) { + throw new IOException("The path " + file + " does not seem to be a valid file path."); + } + iFile.setContents(contents, true/*force*/, true/*keepHistory*/, null/*monitor*/); + } catch (CoreException ex) { + throw new IOException(ex.getMessage()); + } + } + + /** + * Extract the contents of a Jar archive to the specified destination. + */ + public static void unjar(InputStream in, File dest) throws IOException { + if (!dest.exists()) { + dest.mkdirs(); + } + if (!dest.isDirectory()) { + throw new IOException("Destination must be a directory.");//$NON-NLS-1$ + } + JarInputStream jin = new JarInputStream(in); + byte[] buffer = new byte[1024]; + + ZipEntry entry = jin.getNextEntry(); + while (entry != null) { + String fileName = entry.getName(); + if (fileName.charAt(fileName.length() - 1) == '/') { + fileName = fileName.substring(0, fileName.length() - 1); + } + if (fileName.charAt(0) == '/') { + fileName = fileName.substring(1); + } + if (File.separatorChar != '/') { + fileName = fileName.replace('/', File.separatorChar); + } + File file = new File(dest, fileName); + if (entry.isDirectory()) { + // make sure the directory exists + file.mkdirs(); + jin.closeEntry(); + } else { + // make sure the directory exists + File parent = file.getParentFile(); + if (parent != null && !parent.exists()) { + parent.mkdirs(); + } + + // dump the file + OutputStream out = new FileOutputStream(file); + int len = 0; + while ((len = jin.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, len); + } + out.flush(); + out.close(); + jin.closeEntry(); + file.setLastModified(entry.getTime()); + } + entry = jin.getNextEntry(); + } + /* Explicitly write out the META-INF/MANIFEST.MF so that any headers such + as the Class-Path are seen for the unpackaged jar + */ + Manifest mf = jin.getManifest(); + if (mf != null) { + File file = new File(dest, "META-INF/MANIFEST.MF");//$NON-NLS-1$ + File parent = file.getParentFile(); + if (parent.exists() == false) { + parent.mkdirs(); + } + OutputStream out = new FileOutputStream(file); + mf.write(out); + out.flush(); + out.close(); + } + jin.close(); + } + + //Used to Unzip the a specific folder packed inside a plug-in bundle to the plug-in state location + public static File extractFilesFromBundle( URL url, Bundle bundle, String path ) throws Exception { + URL jarUrl = UrlUtil.getJarFileUrl(url); + File jarFile = new File(jarUrl.getFile() ); + Location configLocation = Platform.getConfigurationLocation(); + String pluginId = bundle.getSymbolicName(); + File configFolder = new File( configLocation.getURL().getFile(), pluginId); + File templDir = new File( configFolder, path ); + if( !templDir.exists() ){ + FileUtil.unjar( new FileInputStream( jarFile ), configFolder ); + //Delete un-related files and folders + File[] files = configFolder.listFiles(); + for( File f : files ){ + if( f.isFile() ) + f.delete(); + else if( templDir.getPath().indexOf( f.getPath() ) !=0 ){ + FileUtil.deleteFolder(f); + } + } + } + return templDir ; + } +} + diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java new file mode 100644 index 0000000000..45efe138a2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/StringUtil.java @@ -0,0 +1,648 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.gen.internal2.util; + +import java.beans.Introspector; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class StringUtil +{ + /** + * Pads a string by adding a sequence of an arbitrary character at the beginning. + * @param padChar The character to be used for padding. + * @param len The desired length after padding. + * @return The padded string. For example if <code>str</code> is "f4e" and <code>padChar</code> is '0' + * and <code>len</code> is 6 then this method returns "000f4e" + */ + public static String padLeft(String str, char padChar, int len) { + if(str == null) { + return null; + } + int strLen = str.length(); + if (strLen < len) { + StringBuffer buffer = new StringBuffer(len); + int count = len-strLen; + for (int i = 0; i < count; ++i) + buffer.append(padChar); + buffer.append(str); + str = buffer.toString(); + } + return str; + } + /** + * Inserts a given character at the beginning and at the end of the specified string. + * For example if the string is <tt>extreme</tt> and the char is <tt>'</tt> then + * the returned string is <tt>'exterme'</tt>. + */ + public static String quote(String str, char c) { + assert(str != null); + StringBuffer buffer = new StringBuffer(str.length()+2); + buffer.append(c); + buffer.append(str); + buffer.append(c); + return buffer.toString(); + } + public static String doubleQuote(String str) { + return quote(str, '"'); + } + /** + * Removes the first and last single or double quotes (if they exist). + */ + public static String unquote(String quoted) { + if (quoted != null && quoted.length() >= 2){ + int len = quoted.length(); + char firstChar = quoted.charAt(0); + char lastChar = quoted.charAt(len-1); + if (firstChar == lastChar && (firstChar == '\'' || firstChar == '"')) { + return quoted.substring(1, len-1); + } + } + return quoted; + } + /** + * Truncates a string and adds "..." in the result string. + * If the string length is less or equal to the max len then + * the original string is returned. + */ + public static String truncate(String s, int maxLen) { + if (s == null) { + return null; + } + int len = s.length(); + if (len > maxLen) { + int segmentLen = maxLen/2; + s = s.substring(0, segmentLen) + "..." + s.substring(len-segmentLen); + } + return s; + } + /** + * Returns a string containing the same character repeated. + */ + public static String repeat(char c, int count) { + StringBuffer buffer = new StringBuffer(count); + for (int i = 0; i < count; ++i) { + buffer.append(c); + } + return buffer.toString(); + } + /** + * Returns the given string unless it is emtpty where it returns null. + */ + public static String nullIfEmpty(String s) { + if (s != null && s.length() == 0) { + s = null; + } + return s; + } + /** + * Returns a string containing the same characters as the argument string + * except that the control characters are replaced by the their hex code. + * For example if the string is "ab\nc" the returned string is "ab{0xA}c". + */ + public static String getVisibleString(String s) { + if (s == null) + return null; + int len = s.length(); + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < len; ++i) { + char c = s.charAt(i); + if (c <= 0x1F || (c == 0x20 && (i == 0 || i == len-1))) { + buffer.append("(0x" + Integer.toHexString((int)c).toUpperCase() + ")"); + } + else buffer.append(c); + } + return buffer.toString(); + } + /** + * Replaces a portion of string. + * @param str The original string. + * @param offset The offset in the original string where the replace starts + * @param len The replace length the original string + * @param replaceStr The replacement string + */ + public static String strReplace(String str, int offset, int len, String replaceStr) { + StringBuffer buffer = new StringBuffer(str.length()-len+replaceStr.length()); + buffer.append(str.substring(0, offset)); + buffer.append(replaceStr); + buffer.append(str.substring(offset+len)); + + return buffer.toString(); + } + public static String strReplace(String str, String pattern, String replaceStr) + { + if(str == null) { + return null; + } + if(pattern == null || pattern.equals("")) { + return str; + } + int index = str.indexOf(pattern); + if (index < 0) + return str; + + if (replaceStr == null) + replaceStr = ""; + return str.substring(0, index) + replaceStr + str.substring(index + pattern.length()); + } + public static String strReplaceAll(String str, String pattern, String replaceStr) + { + if(str == null) { + return null; + } + if (replaceStr == null) + replaceStr = ""; + if(pattern == null || pattern.equals("")) { + return str; + } + int index = str.indexOf(pattern); + while (index >= 0) { + str = str.substring(0, index) + replaceStr + str.substring(index + pattern.length()); + index = str.indexOf(pattern, index+replaceStr.length()); + } + return str; + } + public static String strInsert(String str, int index, String insertStr) + { + return str.substring(0, index) + + insertStr + + str.substring(index); + } + /** + * Tokenize the specified string into a <code>List</code> of + * words. + * If the string specified is <code>null</code> or empty, this + * method will return <code>null</code>. + * + * @param s The string to tokenize into a <code>List</code>. + * @param sep The separator character to use to split + * the string. + * @param trim If <code>true</code>, run <code>trim</code> on + * each element in the result <code>List</code>. + * + * @return A <code>List</code> containing all tokenized words + * in the parameter string. + * Each element is of type <code>String</code>. + */ + public static List<String> strToList(String s, char sep, boolean trim) + { + //ex: if sep is ';' then s should be someting like "Red;Black" + if (s == null || s.length() == 0) + return null; + + ArrayList<String> result = new ArrayList<String>(); + + char delimiters[] = {sep}; + java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(s, new String(delimiters), true/*returnDelimiters*/); + String lastTok=null; + while (tokenizer.hasMoreTokens()) { + String tok = tokenizer.nextToken(); + if (tok.length()==1 && tok.charAt(0)==sep){//delimiter + if (tok.equals(lastTok)||lastTok==null/*first element is empty*/) + result.add(""); + } + else{ + if (trim) + tok = tok.trim(); + result.add(tok); + } + lastTok=tok; + } + if(lastTok.length()==1 && lastTok.charAt(0)==sep)//last element is empty + result.add(""); + result.trimToSize(); + return result; + } + public static List<String> strToList(String s, char sep) + { + return strToList(s, sep, false/*trim*/); + } + + @SuppressWarnings("unchecked") + public static String listToStr(Collection a, char sep) + { + return listToStr(a, String.valueOf(sep)); + } + + public static String listToStr(Collection<Object> a, String sep) { + //reverse of strToList + if (a == null) + return null; + int count = a.size(); + if (count == 0) + return null; + + StringBuffer buffer = null; + for (Iterator<Object> iter = a.iterator(); iter.hasNext(); ) + { + Object obj = iter.next(); + if (obj == null) + continue; + + if (buffer == null) + buffer = new StringBuffer(); + else + buffer.append(sep); + if (obj instanceof String) + buffer.append((String)obj); + else + buffer.append(obj); + } + return (buffer != null) ? buffer.toString() : null; + } + /** + * Convert the text of a String into a Map of Strings, where each + * key and value in the Map is of type String. + * + * @param s The string to be converted to a Map. + * @param sep1 The separator between keys and their + * values. + * @param sep2 The separator between key-value pairs. + * + * @return The string converted to a Map. + */ + public static java.util.Map<String, String> strToMap(String s, char sep1, char sep2) + { + return strToMap(s, sep1, sep2, false/*lowercaseKeys*/); + } + /** + * Convert the text of a String into a Map of Strings, where each + * key and value in the Map is of type String. + * This form also allows you to specify that all keys will be + * converted to lower-case before adding to the Map. + * + * @param s The string to be converted to a Map. + * @param sep1 The separator between keys and their + * values. + * @param sep2 The separator between key-value pairs. + * @param lowercaseKeys + * Whether to convert keys to lower case + * before adding to the Map. + * + * @return The string converted to a Map. + */ + public static java.util.Map<String, String> strToMap(String s, char sep1, char sep2, boolean lowercaseKeys) + { + //ex: if sep1 is ':' and sep2 is ',' then s should be something like "color:Red,size:XL" + + if (s == null || s.length() == 0) { + return Collections.emptyMap(); + } + + java.util.List<String> a = strToList(s, sep2); + if (a == null) { + return Collections.emptyMap(); + } + + java.util.HashMap<String, String> hm = new java.util.HashMap<String, String>(); + int count = a.size(); + for (int i = 0; i < count; ++i) + { + String s2 = (String)a.get(i); //ex: color:Red + int pos = s2.indexOf(sep1); + if (pos >= 0) + { + String name = s2.substring(0, pos); + String val = s2.substring(pos+1); + if (lowercaseKeys) + name = name.toLowerCase(); + hm.put(name, val); + } + } + return hm; + } + + @SuppressWarnings("unchecked") + public static String mapToStr(java.util.Map hm, char sep1, char sep2) + //reverse of strToMap + { + if (hm == null || hm.isEmpty()) + return null; + + StringBuffer buffer = new StringBuffer(); + java.util.Iterator<java.util.Map.Entry> iter = hm.entrySet().iterator(); + while (iter.hasNext()) { + java.util.Map.Entry entry = (java.util.Map.Entry)iter.next(); + buffer.append(entry.getKey()); + buffer.append(sep1); + buffer.append(entry.getValue()); + if (iter.hasNext()) { + buffer.append(sep2); + } + } + return buffer.toString(); + } + /** + * Perform a <em>case insensitive</em> comparison between + * the string representations of two objects. + * + * @param obj1 The first object to compare. + * @param obj2 The second object to compare. + * + * @return <code>true</code> if both objects have the + * same case-insensitive string representation. + */ + public static boolean compareAsStrings(Object obj1, Object obj2) + { + if (obj1 == null || obj2 == null) + return obj1 == obj2; + + String s1, s2; + if (obj1 instanceof String) { + s1 = (String)obj1; + } else { + s1 = obj1.toString(); + } + if (obj2 instanceof String) { + s2 = (String)obj2; + } + else { + s2 = obj2.toString(); + } + + return s1.equalsIgnoreCase(s2); + } + /** + * Tests whether a string starts with any of a list of strings. + */ + public static boolean startsWithAny(String s, List<String> prefixes) { + int count = prefixes.size(); + for (int i = 0; i < count; ++i) { + if (s.startsWith((String)prefixes.get(i))) { + return true; + } + } + return false; + } + /** + * Returns the argument string with the first char upper-case. + */ + public static String initUpper(String str) { + if (str == null || str.length() == 0) { + return str; + } + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } + /** + * Returns the argument string with the first char lower-case. + */ + public static String initLower(String str) { + if (str == null || str.length() == 0) { + return str; + } + return Character.toLowerCase(str.charAt(0)) + str.substring(1); + } + /** + * Tests whether all characters in the given string are upper + * case. + */ + public static boolean isUpperCase(String s) { + return s.toUpperCase().equals(s); + } + /** + * Returns the first non-white char index starting from the + * specified index. + */ + public static int skipWhiteSpaces(String str, int index) { + int len = str.length(); + while (index < len) { + if (!Character.isWhitespace(str.charAt(index))) { + break; + } + ++index; + } + return index; + } + /** + * Collapses consecutive white spaces into one space. + */ + public static String collapseWhiteSpaces(String str){ + String result=null; + if (str!=null){ + StringBuffer buffer=new StringBuffer(); + boolean isInWhiteSpace=false; + for (int i=0;i<str.length();i++){ + char c=str.charAt(i); + if (Character.isWhitespace(c)){ + isInWhiteSpace=true; + } + else { + if (isInWhiteSpace) + buffer.append(" "); + isInWhiteSpace=false; + buffer.append(c); + } + } + result=buffer.toString(); + } + return result; + } + + /** + * Utility methods used to convert DB object names to + * appropriate Java type and field name + */ + public static String pluralise(String name) { + String result = name; + if (name.length() == 1) { + result += 's'; + } else if (!seemsPluralised(name)) { + String lower = name.toLowerCase(); + if (!lower.endsWith("data")) { //orderData --> orderDatas is dumb + char secondLast = lower.charAt(name.length() - 2); + if (!isVowel(secondLast) && lower.endsWith("y")) { + // city, body etc --> cities, bodies + result = name.substring(0, name.length() - 1) + "ies"; + } else if (lower.endsWith("ch") || lower.endsWith("s")) { + // switch --> switches or bus --> buses + result = name + "es"; + } else { + result = name + "s"; + } + } + } + return result; + } + + public static String singularise(String name) { + String result = name; + if (seemsPluralised(name)) { + String lower = name.toLowerCase(); + if (lower.endsWith("ies")) { + // cities --> city + result = name.substring(0, name.length() - 3) + "y"; + } else if (lower.endsWith("ches") || lower.endsWith("ses")) { + // switches --> switch or buses --> bus + result = name.substring(0, name.length() - 2); + } else if (lower.endsWith("s")) { + // customers --> customer + result = name.substring(0, name.length() - 1); + } + } + return result; + } + private final static boolean isVowel(char c) { + boolean vowel = false; + vowel |= c == 'a'; + vowel |= c == 'e'; + vowel |= c == 'i'; + vowel |= c == 'o'; + vowel |= c == 'u'; + vowel |= c == 'y'; + return vowel; + } + private static boolean seemsPluralised(String name) { + name = name.toLowerCase(); + boolean pluralised = false; + pluralised |= name.endsWith("es"); + pluralised |= name.endsWith("s"); + pluralised &= !(name.endsWith("ss") || name.endsWith("us")); + return pluralised; + } + + /** + * Returns the package name of a class name. + * For example if given <code>oracle.util.ObjectUtil</code> it would return + * <code>oracle.util</code>. If the class is not in a package then null is returned. + */ + public static String getPackageName(String className) { + if(className == null) { + return null; + } + int lastDotIndex = className.lastIndexOf('.'); + if (lastDotIndex < 0) + return null; + return className.substring(0, lastDotIndex); + } + /** + * Returns the class name given a full class name. + * For example if given <code>oracle.util.ObjectUtil</code> it would return + * <code>ObjectUtil</code> + */ + public static String getClassName(String fullClassName) { + if(fullClassName == null) { + return null; + } + int lastDotIndex = fullClassName.lastIndexOf('.'); + if (lastDotIndex < 0) + return fullClassName; + return fullClassName.substring(lastDotIndex+1); + } + + + /** + * Converts a database column name to a Java variable name (<em>first letter + * not capitalized</em>). + */ + public static String columnNameToVarName(String columnName) { + return dbNameToVarName(columnName); + } + /** + * Converts a database table name to a Java variable name (<em>first letter + * not capitalized</em>). + */ + public static String tableNameToVarName(String tableName) { + return dbNameToVarName(tableName); + } + /** + * Converts a database name (table or column) to a java name (<em>first letter + * not capitalized</em>). employee_name or employee-name -> employeeName + */ + private static String dbNameToVarName(String s) { + if ("".equals(s)) { + return s; + } + StringBuffer result = new StringBuffer(); + + boolean capitalize = true; + boolean lastCapital = false; + boolean lastDecapitalized = false; + String p = null; + for (int i = 0; i < s.length(); i++) { + String c = s.substring(i, i + 1); + if ("_".equals(c) || " ".equals(c)) { + capitalize = true; + continue; + } + + if (c.toUpperCase().equals(c)) { + if (lastDecapitalized && !lastCapital) { + capitalize = true; + } + lastCapital = true; + } else { + lastCapital = false; + } + + if (capitalize) { + if (p == null || !p.equals("_")) { + result.append(c.toUpperCase()); + capitalize = false; + p = c; + } else { + result.append(c.toLowerCase()); + capitalize = false; + p = c; + } + } else { + result.append(c.toLowerCase()); + lastDecapitalized = true; + p = c; + } + + } + /*this was using StringUtil.initLower. Changed to Introspector.decapitalize so that + * it returns the correct bean property name when called from columnNameToVarName. + * This is necessary because otherwise URL would be uRL which would cause + * an "The property uRL is undefined for the type xx" error because + * Introspector.getBeanInfo (used by JavaTypeIntrospector) returns + * the property name as URL.*/ + String resultStr = Introspector.decapitalize(result.toString()); + if (resultStr.equals("class")) { + // "class" is illegal becauseOf Object.getClass() clash + resultStr = "clazz"; + } + return resultStr; + } + + /** + * Compare two objects. If both String, ignore case + * @param o1 + * @param o2 + * @param ignoreCaseIfStr + * @return + */ + public static boolean equalObjects(Object o1, Object o2, boolean ignoreCaseIfStr) + { + if (o1 == o2) { + return true; + } + boolean result; + if (o1 == null || o2 == null) { + return false; //we already checked o1 == o2 above + } + if (ignoreCaseIfStr && o1 instanceof String && o2 instanceof String) + result = ((String)o1).equalsIgnoreCase((String)o2); + else + result = o1.equals(o2); + + return result; + } + + public static boolean equalObjects(Object o1, Object o2) + { + return equalObjects(o1, o2, false/*ignoreCaseIfStr*/); + } + +} + diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java new file mode 100644 index 0000000000..f6b5276726 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal2/util/UrlUtil.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.gen.internal2.util; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.osgi.framework.Bundle; + +/** + * Collections of utility methods handling URLs. + * + */ +public class UrlUtil +{ + /** + * The <code>file</code> string indicating a url file protocol. + */ + public static final String FILE_PROTOCOL = "file"; + /** + * The <code>file</code> string indicating a url http protocol. + */ + public static final String HTTP_PROTOCOL = "http"; + /** + * The <code>file</code> string indicating a url http protocol. + */ + public static final String HTTPS_PROTOCOL = "https"; + /** + * The <code>file</code> string indicating a url file protocol. + */ + public static final String JAR_PROTOCOL = "jar"; + + + /** + * Returns true if the specified url is to a file, i.e its protocol is <code>file</code>. + */ + public static boolean isFileUrl(URL url) { + return url != null && FILE_PROTOCOL.equals(url.getProtocol()); + } + /** + * Returns true if the specified url is to a jar, i.e its protocol is <code>jar</code>. + * For example <code>jar:file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld</code>. + */ + public static boolean isJarUrl(URL url) { + return url != null && JAR_PROTOCOL.equals(url.getProtocol()); + } + /** + * Returns true if the specified url protocol is http. + */ + public static boolean isHttpUrl(URL url) { + String protocol = url.getProtocol(); + return url != null && (HTTP_PROTOCOL.equals(protocol) || HTTPS_PROTOCOL.equals(protocol)); + } + /** + * Returns the <code>File</code> corresponding to a url, or null if the url + * protocol is not file. + */ + public static java.io.File getUrlFile(URL url) { + if (isFileUrl(url) && !isJarUrl( url ) ){ + File ret = new java.io.File(url.getFile()); + return ret ; + } + return null; + } + + + /** + * Returns the url to a jar file given a url to a file inside + * the jar. + * For example if given + * <code>jar:file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld</code> + * this method returns <code>file:/C:/testapps/example/WEB-INF/lib/struts.jar</code>. + * + * <p>Returns null if the given url is not recognized as a url to a file + * inside a jar. + */ + public static URL getJarFileUrl(URL url) { + if (!isJarUrl(url)) { + return null; + } + String file = url.getFile(); //file:/C:/testapps/example/WEB-INF/lib/struts.jar!/META-INF/tlds/struts-bean.tld + int index = file.indexOf('!'); + if (index < 0) { + return null; + } + String jarFileUrlStr = file.substring(0, index); + try { + return new URL(jarFileUrlStr); + } catch (MalformedURLException e) { + return null; + } + } + + public static boolean isRemote(String url){ + return url.startsWith("http:")||url.startsWith("https:")||url.startsWith("www."); + } + + public static File getTemplateFolder(String plugId , String strPath ){ + Bundle bundle = Platform.getBundle( plugId ); + Path path = new Path( strPath ); + URL url = FileLocator.find(bundle, path, null); + try { + URL templUrl; + templUrl = FileLocator.resolve(url); + File templDir = UrlUtil.getUrlFile(templUrl); + return templDir ; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm new file mode 100644 index 0000000000..8bb49108b2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/column.vm @@ -0,0 +1,52 @@ +##included template. Generates the @Column annotation. +##Assumes that the context has a "column" and a "table" object +##generate annotation only the parameters for the column NOT default +##and the generateDLLAnnotation property is not set on the table +###------------------------------------------------ +#macro( append $members $parameters ) +#if( $members == "") +#set( $members = $parameters ) +#else +#set( $members = "$members, $parameters" ) +#end +#end +###------------------------------------------------ +#if ( $column.dataTypeLOB) + @Lob() +#end +#if ( $column.needMapTemporalType) + @Temporal( TemporalType.$column.temporalType) +#end +#set ($members = "") +#if ( !$column.default || $table.generateDDLAnnotations ) +#set ($members = "name=$customizer.quote($column.name)") +#if (!$column.insertable) +#set ($members = "$members, insertable=false") +#end +#if (!$column.updateable) +#set ($members = "$members, updatable=false") +#end +#end +#if( $table.generateDDLAnnotations ) +#if ($column.unique) +#append($members "unique=true") +#end +#if (!$column.nullable) +#append($members "nullable=false") +#end +#if ($column.size > 0) +#if ($column.numeric) +#append($members "precision=$column.size") +#if ($column.decimalDigits != 0 && $column.decimalDigits != -1) +#append($members "scale=$column.decimalDigits") +#end +#else +#if ( !$column.dataTypeLOB) +#append($members "length=$column.size") +#end +#end +#end +#end +#if( $members !="" ) + @Column($members) +#end diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm new file mode 100644 index 0000000000..ece3ff4c3f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/join.vm @@ -0,0 +1,61 @@ +##included template. Generates the @JoinTable, @JoinColumn or @JoinColumns annotation. +##Assumes that the context has a "role" object representing the generated AssociationRole +## +##macro joinColumn uses $column, $referencedColumn +#macro (joinColumn $column $referencedColumn) +#set ($members = "name=$customizer.quote($column.joinColumnName)") +#if( !$referencedColumn.primaryKey ) +#set ($members = "$members, referencedColumnName=$customizer.quote($referencedColumn.name)") +#end +#if( $table.generateDDLAnnotations ) +#if ($column.unique && !$column.primaryKey) +#set ($members = "$members, unique=true") +#end +#if (!$column.nullable) +#set ($members = "$members, nullable=false") +#end +#end +#if (!$role.association.joinTable && !$role.referrerTable.isColumnUpdateInsert($role, $column)) +#set ($members = "$members, insertable=false, updatable=false") +#end +@JoinColumn($members)#end +## +## +## +#if ($role.association.joinTable) +#set ($joinTable = $role.association.joinTable) + @JoinTable( + name="${joinTable.joinTableAnnotationName}" +#if ($joinTable.schema!="") + , schema="${joinTable.schema}" +#end + , joinColumns={ +#foreach ($column in $role.referrerColumns) +#set ($referencedColumn = $role.getReferencedColumn(${column.name})) +##$referencedColumn is the column in the join table + #joinColumn($referencedColumn $column), +#end + } + , inverseJoinColumns={ +#foreach ($column in $role.referencedColumns) +#set ($referencedColumn = $role.getReferrerColumn(${column.name})) +##$referencedColumn is the column in the join table + #joinColumn($referencedColumn $column), +#end + } + ) +#else +#if ($role.referrerColumns.size() == 1) +#set ($column = $role.referrerColumns.get(0)) +#set ($referencedColumn = $role.getReferencedColumn(${column.name})) + #joinColumn($column $referencedColumn) + +#else + @JoinColumns({ +#foreach ($column in $role.referrerColumns) +#set ($referencedColumn = $role.getReferencedColumn(${column.name})) + #joinColumn($column $referencedColumn), +#end + }) +#end +#end
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm new file mode 100644 index 0000000000..28c861c844 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/main.java.vm @@ -0,0 +1,129 @@ +#if ($table.package != "") +package ${table.package}; +#end +import java.io.Serializable; +import javax.persistence.*; + +/** + * The persistent class for the ${table.name} database table. + * + */ +@Entity +@Table(name="${table.name}") +public class ${table.className} ${table.generateExtendsImplements()} { + private static final long serialVersionUID = 1L; +##### +##### fields +##### +#if ($table.compositeKey) +#if ($table.access == "field") + + @EmbeddedId +#end + private ${table.compositeKeyClassName} ${table.compositeKeyPropertyName}; +#end +#foreach ($column in $table.getSimpleColumns(true, true, false)) +#if ($table.access == "field") + +#parse("mappingKind.vm") +#parse("column.vm") +#end + ${column.fieldScope} ${column.propertyType} ${column.propertyName}; +#end +#foreach ($role in $table.associationRoles) +##### +##### field annotations +##### +#if ($table.access == "field") + + //${role.description} +#if ($role.cardinality == "many-to-one") +#parse("manyToOne.vm") +#elseif ($role.cardinality == "many-to-many") +#parse("manyToMany.vm") +#elseif ($role.cardinality == "one-to-many") +#parse("oneToMany.vm") +#elseif ($role.cardinality == "one-to-one") +#parse("oneToOne.vm") +#end +#end +##### +##### field declaration +##### +#if ($role.cardinality == "many-to-one" || $role.cardinality == "one-to-one") +#set ($propertyType = ${role.referencedTable.className}) +#elseif ($role.cardinality == "many-to-many" || $role.cardinality == "one-to-many") +#set ($propertyType = "${role.referencedTable.defaultCollectionType}<${role.referencedTable.className}>") +#end + private $propertyType $role.propertyName; +#end + + public ${table.className}() { + } +##### +##### simple properties getters and setters +##### +#if ($table.compositeKey) +#if ($table.access == "property") + + @EmbeddedId +#end + public $table.compositeKeyClassName $customizer.propertyGetter($table.compositeKeyPropertyName)() { + return this.${table.compositeKeyPropertyName}; + } + + public void $customizer.propertySetter($table.compositeKeyPropertyName)($table.compositeKeyClassName $table.compositeKeyPropertyName) { + this.${table.compositeKeyPropertyName} = ${table.compositeKeyPropertyName}; + } + +#end +#foreach ($column in $table.getSimpleColumns(true, true, false)) +#if ($table.access == "property") + +#parse("mappingKind.vm") +#parse("column.vm") +#end + $column.propertyGetScope $column.propertyType $customizer.propertyGetter($column.propertyName)() { + return this.${column.propertyName}; + } + + $column.propertySetScope void $customizer.propertySetter($column.propertyName)($column.propertyType $column.propertyName) { + this.${column.propertyName} = ${column.propertyName}; + } + +#end +##### +##### associations getters and setters +##### +#foreach ($role in $table.associationRoles) +#if ($table.access == "property") + + //${role.description} +#if ($role.cardinality == "many-to-one") +#parse("manyToOne.vm") +#elseif ($role.cardinality == "many-to-many") +#parse("manyToMany.vm") +#elseif ($role.cardinality == "one-to-many") +#parse("oneToMany.vm") +#elseif ($role.cardinality == "one-to-one") +#parse("oneToOne.vm") +#end +#end +## +#if ($role.cardinality == "many-to-one" || $role.cardinality == "one-to-one") +#set ($propertyType = $role.referencedTable.className) +#elseif ($role.cardinality == "many-to-many" || $role.cardinality == "one-to-many") +#set ($propertyType = "${role.referencedTable.defaultCollectionType}<${role.referencedTable.className}>") +#end + public $propertyType $customizer.propertyGetter($role.propertyName)() { + return this.${role.propertyName}; + } + + public void ${customizer.propertySetter($role.propertyName)}($propertyType $role.propertyName) { + this.${role.propertyName} = $role.propertyName; + } + +## +#end +## +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm new file mode 100644 index 0000000000..fe3bfedd8b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToMany.vm @@ -0,0 +1,14 @@ +##included template. Generates the @ManyToMany annotation. +##Assumes that the context has a "role" object representing the generated AssociationRole +## +#if ($role.association.bidirectional && !$role.isReferrerRole())##the owning side (either side for many-to-many) +#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true)) +#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @ManyToMany($members) +#else +#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @ManyToMany($members) +#parse("join.vm") +#end
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm new file mode 100644 index 0000000000..8253462972 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/manyToOne.vm @@ -0,0 +1,7 @@ +##included template. Generates the @ManyToOne annotation. +##Assumes that the context has a "role" object representing the generated AssociationRole +## +#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @ManyToOne($members) +#parse("join.vm")
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm new file mode 100644 index 0000000000..4bc95386e3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/mappingKind.vm @@ -0,0 +1,30 @@ +##included template. Generates the @Basic, @Id, @Version annotations. +##Assumes that the context has a "column" object +## +#set ($mappingKind = $column.mappingKind) +#if ($mappingKind == "id") + @Id +#set ($idGenerator = $table.idGenerator) +#if ($idGenerator == "auto") +#set ($generationType = "GenerationType.AUTO") +#elseif ($idGenerator == "identity") +#set ($generationType = "GenerationType.IDENTITY") +#elseif ($idGenerator == "sequence") +#set ($generationType = "GenerationType.SEQUENCE") +#elseif ($idGenerator == "table") +#set ($generationType = "GenerationType.TABLE") +#else +#set ($generationType = "") +#end +#if ($idGenerator == "sequence" || ($idGenerator == "auto" && $table.sequence)) +#set ($generatorName = "${table.name.toUpperCase()}_${column.propertyName.toUpperCase()}_GENERATOR") + @SequenceGenerator(name="$generatorName", sequenceName="$table.formattedSequence") + @GeneratedValue(strategy=$generationType, generator="$generatorName") +#elseif ($generationType != "") + @GeneratedValue(strategy=$generationType) +#end +#elseif ($mappingKind == "version") + @Version() +#else +##DEFAULT is @Basic(), no need to generate +#end
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm new file mode 100644 index 0000000000..bb89d5b885 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToMany.vm @@ -0,0 +1,14 @@ +##included template. Generates the @OneToMany annotation. +##Assumes that the context has a "role" object representing the generated AssociationRole +## +#if ($role.association.bidirectional) +#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true)) +#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @OneToMany($members) +#else +#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @OneToMany($members) +#parse("join.vm") +#end
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm new file mode 100644 index 0000000000..862c967802 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/oneToOne.vm @@ -0,0 +1,14 @@ +##included template. Generates the @OneToOne annotation. +##Assumes that the context has a "role" object representing the generated AssociationRole +## +#if ($role.association.bidirectional && !$role.isReferrerRole())##the owning side (either side for one-to-one) +#set ($members = $customizer.appendAnnotation("", "mappedBy", $role.oppositeRole.propertyName, true)) +#set ($members = $customizer.appendAnnotation($members, "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @OneToOne($members) +#else +#set ($members = $customizer.appendAnnotation("", "cascade", $customizer.genCascades($role), false)) +#set ($members = $customizer.appendAnnotation($members, "fetch", $customizer.genFetch($role.referrerTable), false)) + @OneToOne($members) +#parse("join.vm") +#end
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm new file mode 100644 index 0000000000..780037e8a9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/templates/entities/pk.java.vm @@ -0,0 +1,65 @@ +#if ($table.package != "") +package ${table.package}; +#end +import java.io.Serializable; +import javax.persistence.*; + +/** + * The primary key class for the ${table.name} database table. + * + */ +@Embeddable() +public class ${table.compositeKeyClassName} implements Serializable { + //default serial version id, required for serializable classes. + private static final long serialVersionUID = 1L; +##### +##### fields +##### +#foreach ($column in $table.primaryKeyColumns) +#if ($table.access == "field") + +#parse("column.vm") +#end + ${column.fieldScope} ${column.propertyType} ${column.propertyName}; +#end + + public ${table.compositeKeyClassName}() { + } +##### +##### simple properties getters and setters +##### +#foreach ($column in $table.primaryKeyColumns) +#if ($table.access == "property") + +#parse("column.vm") +#end + $column.propertyGetScope $column.propertyType $customizer.propertyGetter($column.propertyName)() { + return this.${column.propertyName}; + } + $column.propertySetScope void $customizer.propertySetter($column.propertyName)($column.propertyType $column.propertyName) { + this.${column.propertyName} = ${column.propertyName}; + } +#end +## +## equals/hashCode + + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof ${table.compositeKeyClassName})) { + return false; + } + ${table.compositeKeyClassName} castOther = (${table.compositeKeyClassName})other; + return + ${table.primaryKeyEqualsClause} + + } + + public int hashCode() { + final int prime = 31; + int hash = 17; + ${table.primaryKeyHashCodeClause} + return hash; + } +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF index fc2248781b..d1585a5ef4 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF +++ b/jpa/plugins/org.eclipse.jpt.ui/META-INF/MANIFEST.MF @@ -43,7 +43,8 @@ Require-Bundle: org.eclipse.core.expressions;bundle-version="[3.4.0,4.0.0)", org.eclipse.wst.common.project.facet.core;bundle-version="[1.3.0,2.0.0)", org.eclipse.wst.common.project.facet.ui;bundle-version="[1.3.0,2.0.0)", org.eclipse.wst.sse.ui;bundle-version="[1.1.0,1.2.0)", - org.eclipse.wst.web.ui;bundle-version="[1.1.200,2.0.0)" + org.eclipse.wst.web.ui;bundle-version="[1.1.200,2.0.0)", + org.eclipse.gef;bundle-version="[3.5.0,4.0.0)" Export-Package: org.eclipse.jpt.ui, org.eclipse.jpt.ui.details, org.eclipse.jpt.ui.internal;x-internal:=true, diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif Binary files differnew file mode 100644 index 0000000000..864034f74e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add-connection.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png Binary files differnew file mode 100644 index 0000000000..6bd3486b7a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/add.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png Binary files differnew file mode 100644 index 0000000000..1f64f24965 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse-mini.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png Binary files differnew file mode 100644 index 0000000000..8081fd9293 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/browse.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png Binary files differnew file mode 100644 index 0000000000..3582d18d5b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/collapse-all.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png Binary files differnew file mode 100644 index 0000000000..afba8b4463 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/delete.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png Binary files differnew file mode 100644 index 0000000000..49544f5703 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/deselect-all.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif Binary files differnew file mode 100644 index 0000000000..57a514d649 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/dot.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png Binary files differnew file mode 100644 index 0000000000..306d6a1c5f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/edit.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png Binary files differnew file mode 100644 index 0000000000..db729a3990 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/expand-all.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png Binary files differnew file mode 100644 index 0000000000..8081fd9293 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/list-of-values.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png Binary files differnew file mode 100644 index 0000000000..f6e5281b70 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-down.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png Binary files differnew file mode 100644 index 0000000000..7c8b1ccf79 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/move-up.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png Binary files differnew file mode 100644 index 0000000000..df009468ab --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/reconnect.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png Binary files differnew file mode 100644 index 0000000000..2d74ae4e01 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/restore-defaults.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png Binary files differnew file mode 100644 index 0000000000..4eaff2beab --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/select-all.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png Binary files differnew file mode 100644 index 0000000000..a7b471c2d3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/buttons/warningstd.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png Binary files differnew file mode 100644 index 0000000000..0751b3267c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img-hover.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png Binary files differnew file mode 100644 index 0000000000..5fb4dc2a2c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/export-as-img.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png Binary files differnew file mode 100644 index 0000000000..abfffe4bc7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_left_bg.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png Binary files differnew file mode 100644 index 0000000000..caa828d3c0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_mid_bg.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png Binary files differnew file mode 100644 index 0000000000..bd7414470c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/header_right_bg.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png Binary files differnew file mode 100644 index 0000000000..468a09b5de --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print-hover.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png Binary files differnew file mode 100644 index 0000000000..ee15ba107e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/print.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png Binary files differnew file mode 100644 index 0000000000..d84b339401 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-bottom.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png Binary files differnew file mode 100644 index 0000000000..fa25df32e8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-left.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png Binary files differnew file mode 100644 index 0000000000..a58c953f1a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-lower-right.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png Binary files differnew file mode 100644 index 0000000000..585ed6a9e4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-side.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png Binary files differnew file mode 100644 index 0000000000..ccabb96f5c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/shadow-upper-right.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png Binary files differnew file mode 100644 index 0000000000..c483a49336 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/diagram/toolbar_bg.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif Binary files differnew file mode 100644 index 0000000000..5f1551ba96 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/column.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif Binary files differnew file mode 100644 index 0000000000..4f385155d6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/columnKey.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png Binary files differnew file mode 100644 index 0000000000..f5c1810a63 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/file.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png Binary files differnew file mode 100644 index 0000000000..9759da4e20 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/folder.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif Binary files differnew file mode 100644 index 0000000000..562bd70b5c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/forward.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif Binary files differnew file mode 100644 index 0000000000..7a1511dd8e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/moveRight.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png b/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png Binary files differnew file mode 100644 index 0000000000..471cc4367d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/package.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif Binary files differnew file mode 100644 index 0000000000..a99388a9af --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif Binary files differnew file mode 100644 index 0000000000..e2ccabb383 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/objects/table_obj.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif Binary files differnew file mode 100644 index 0000000000..119dcccd5a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/error.gif diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png Binary files differnew file mode 100644 index 0000000000..8c1e86c479 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/overlays/warning.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png b/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png Binary files differnew file mode 100644 index 0000000000..eca4774fec --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/images/save-image-16.png diff --git a/jpa/plugins/org.eclipse.jpt.ui/plugin.properties b/jpa/plugins/org.eclipse.jpt.ui/plugin.properties index 377baeecf2..18ce474a46 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/plugin.properties +++ b/jpa/plugins/org.eclipse.jpt.ui/plugin.properties @@ -33,6 +33,8 @@ newJpaEntityWizardName = Entity newJpaEntityWizardDesc = Create a JPA Entity newJpaMappingFileWizardName = Mapping File newJpaMappingFileWizardDesc = Create a JPA Mapping File +newJpaEntityFromTableWizardName = Entities From Tables +newJpaEntityFromTableWizardDesc = Create JPA Entities from database tables jpaStructureViewCommandCategory = JPA Structure View addPersistentClass = Add Class ... diff --git a/jpa/plugins/org.eclipse.jpt.ui/plugin.xml b/jpa/plugins/org.eclipse.jpt.ui/plugin.xml index 3d6f7ab3fd..597cb1bbb7 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/plugin.xml +++ b/jpa/plugins/org.eclipse.jpt.ui/plugin.xml @@ -541,6 +541,30 @@ --> + <commonWizard + menuGroupId="org.eclipse.jpt.ui" + type="new" + wizardId="org.eclipse.jpt.ui.wizard.newEntitiesFromTables"> + <enablement> + <and> + <or> + <instanceof + value="org.eclipse.core.resources.IProject"/> + <instanceof + value="org.eclipse.jdt.core.IPackageFragment"/> + <instanceof + value="org.eclipse.jdt.core.IPackageFragmentRoot"/> + </or> + <adapt type="org.eclipse.core.resources.IResource"> + <test + forcePluginActivation="true" + property="org.eclipse.wst.common.project.facet.core.projectFacet" + value="jpt.jpa" /> + </adapt> + </and> + </enablement> + </commonWizard> + </navigatorContent> </extension> @@ -581,6 +605,16 @@ </wizard> <wizard + category="org.eclipse.jpt" + class="org.eclipse.jpt.ui.internal.wizards.gen.GenerateEntitiesFromSchemaWizard" + icon="platform:/plugin/org.eclipse.jpt.ui/icons/full/etool16/new_entity_wiz.gif" + id="org.eclipse.jpt.ui.wizard.newEntitiesFromTables" + name="%newJpaEntityFromTableWizardName"> + <description>%newJpaEntityFromTableWizardDesc</description> + <selection class="org.eclipse.core.resources.IResource"/> + </wizard> + + <wizard id="org.eclipse.jpt.ui.wizard.newMappingFile" name="%newJpaMappingFileWizardName" icon="icons/full/etool16/new_jpa_file_wiz.gif" diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties new file mode 100644 index 0000000000..9b8c42a7da --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_entity_gen.properties @@ -0,0 +1,128 @@ +############################################################################### +# Copyright (c) 2006, 2008 Oracle. All rights reserved. +# This program and the accompanying materials are made available under the terms of +# the Eclipse Public License v1.0, which accompanies this distribution and is available at +# http://www.eclipse.org/legal/epl-v10.html. +# +# Contributors: +# Oracle - initial API and implementation +############################################################################### + +cardinality=Car&dinality: +property=P&roperty: +cascade=&Cascade: +databaseSettings=Database Settings +connection=&Connection: +schema=&Schema: +schemaInfo=(Note: You must have an active connection to select schema.) +addConnectionLink=Add connections... +reconnectLink=Reconnect... +connectLink=Connect +connectingMessage=Connecting... +manyToOne=&Many to one +manyToMany=Man&y to many +oneToMany=&One to many +oneToOne=&One to one +manyToOneDesc=Each %s has many %s. +oneToOneDesc=There is one %s per %s. +manyToManyDesc=Each %s has many %s, and each %s has many %s. + +add=&Add +remove=&Remove +browse=B&rowse... + +showInSchemaViewer=Show in Schema Viewer +showInEntityEditor=Show in Entity Relationship Editor + +GenerateEntitiesWizard_generateEntities=Generate Custom Entities + +GenerateEntitiesWizard_selectJPAProject=JPA Project Selection +GenerateEntitiesWizard_selectJPAProject_msg=Select a JPA project. +GenerateEntitiesWizard_selectJPAProject_label=JPA projects in the workspace: + +GenerateEntitiesWizard_tableSelectPage_selectTable=Select Tables +GenerateEntitiesWizard_tableSelectPage_chooseEntityTable=Select tables to generate entities from. +GenerateEntitiesWizard_tableSelectPage_synchronizeClasses=Synchronize classes listed in persistence.xml +GenerateEntitiesWizard_tableSelectPage_copyJdbcDrive = Add JDBC driver to project classpath +GenerateEntitiesWizard_tableSelectPage_tables=&Tables: +GenerateEntitiesWizard_tableSelectPage_tableColumn=Table + +GenerateEntitiesWizard_assocPage_title=Table Associations +GenerateEntitiesWizard_assocPage_label=Table &associations +GenerateEntitiesWizard_assocPage_desc=Edit a table association by selecting it and modifying the controls in the editing panel. +GenerateEntitiesWizard_assocPage_newAssoc=New Association +GenerateEntitiesWizard_assocPage_delAssoc=Delete Selected Association + + +GenerateEntitiesWizard_defaultTablePage_title=Customize Default Entity Generation +GenerateEntitiesWizard_defaultTablePage_tableMapping=Table Mapping +GenerateEntitiesWizard_defaultTablePage_domainJavaClass=Domain Java Class + +GenerateEntitiesWizard_defaultTablePage_desc=Optionally customize aspects of entities that will be generated by default from database tables. A Java package should be specified. +GenerateEntitiesWizard_defaultTablePage_access=Entity &access: +GenerateEntitiesWizard_defaultTablePage_fetch=Associations &fetch: +GenerateEntitiesWizard_defaultTablePage_collType=Collection properties &type: +GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations = Always generate optional JPA annotations and DDL parameters +GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc = Generate optional JPA annotations and DDL parameters like 'unique', 'nullable', 'length', 'precision' and 'scale', which are optional and only used by automatic table creation to specify table creation data. +GenerateEntitiesWizard_defaultTablePage_keyGen=Key &generator: +GenerateEntitiesWizard_defaultTablePage_sequence=Sequence &name: +GenerateEntitiesWizard_defaultTablePage_sequenceNote=You can use the patterns %s and/or %s in the sequence name.\n\ + These patterns will be replaced by the table name and the primary key \n\ + column name when a table mapping is generated. +GenerateEntitiesWizard_defaultTablePage_package=Java Package *: +GenerateEntitiesWizard_defaultTablePage_baseClass=Base Class: +GenerateEntitiesWizard_defaultTablePage_interfaces=Interfaces: +GenerateEntitiesWizard_defaultTablePage_chooseInterfaces=Choose Class Interfaces + +GenerateEntitiesWizard_tablesAndColumnsPage_title=Customize Individual Entities +GenerateEntitiesWizard_tablesAndColumnsPage_desc=Customize detail of individual entities by selecting the associated tables or columns and changing values in the editing panel. +GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns=&Tables and columns +GenerateEntitiesWizard_tablesAndColumnsPage_tableMapping=Table Mapping +GenerateEntitiesWizard_tablesAndColumnsPage_columnMapping=Column Mapping + +GenerateEntitiesWizard_tablePanel_className=&Class name: +GenerateEntitiesWizard_tablePanel_implementEq=Implement equals/hashCode +GenerateEntitiesWizard_colPanel_genProp=Generate this property +GenerateEntitiesWizard_colPanel_colMapping=Column mapping +GenerateEntitiesWizard_colPanel_propName=Property &name: +GenerateEntitiesWizard_colPanel_propType=Mapping t&ype: +GenerateEntitiesWizard_colPanel_mapKind=Mapping &kind: +GenerateEntitiesWizard_colPanel_beanProp=Domain Java Class +GenerateEntitiesWizard_colPanel_getterScope=Getter Scope: +GenerateEntitiesWizard_colPanel_setterScope=Setter Scope: +GenerateEntitiesWizard_colPanel_colUpdateable=Column is &updatable +GenerateEntitiesWizard_colPanel_colInsertable=Column is &insertable +GenerateEntitiesWizard_colPanel_useInToString=Use in toString +GenerateEntitiesWizard_colPanel_useInEquals=Use in equals/hashCode + +GenerateEntitiesWizard_newAssoc_title=Create New Association +GenerateEntitiesWizard_newAssoc_exists=A similar association between %s and %s already exists. + +GenerateEntitiesWizard_newAssoc_tablesPage_title=Association Tables +GenerateEntitiesWizard_newAssoc_tablesPage_desc=Specify the association tables. +GenerateEntitiesWizard_tablesSelPage_newConn=New... +GenerateEntitiesWizard_newAssoc_tablesPage_assocKind=Association Kind +GenerateEntitiesWizard_newAssoc_tablesPage_assocTables=Association &tables: +GenerateEntitiesWizard_newAssoc_tablesPage_table1=Table &1: +GenerateEntitiesWizard_newAssoc_tablesPage_table2=Table &2: +GenerateEntitiesWizard_newAssoc_tablesPage_intermediateTable=Join Table: +GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc=&Simple association +GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc=&Many to many association + +GenerateEntitiesWizard_newAssoc_cardinalityPage_title=Association Cardinality +GenerateEntitiesWizard_newAssoc_cardinalityPage_desc=Specify the association cardinality. + +GenerateEntitiesWizard_newAssoc_colsPage_title=Join Columns +GenerateEntitiesWizard_newAssoc_colsPage_desc=Specify the join columns. +GenerateEntitiesWizard_newAssoc_colsPage_label=Specify the join columns between the %s and %s tables: + +GenerateEntitiesWizard_assocEditor_entityRef=Generate a reference to %s in %s +GenerateEntitiesWizard_assocEditor_setRef=Generate a reference to a collection of %s in %s +GenerateEntitiesWizard_assocEditor_tableJoin=Table &join: +GenerateEntitiesWizard_assocEditor_joinedWhen=The table rows are joined when:\n%s +GenerateEntitiesWizard_assocEditor_genAssoc=Generate &this association +GenerateEntitiesWizard_fileWillBeOverwritten = Note that the generated .java files will *overwrite* existing files with the same name. +GenerateEntitiesWizard_doNotShowWarning = Don't show me this warning again + +GenerateEntitiesWizard_inconsistentConn=The selected connection url is different than the connection url specified in the "%s" file . + diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java new file mode 100644 index 0000000000..a0980ff0bd --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/CommonImages.java @@ -0,0 +1,101 @@ +package org.eclipse.jpt.ui; + +import static org.eclipse.jpt.ui.JptUiPlugin.PLUGIN_ID; +import static org.eclipse.ui.plugin.AbstractUIPlugin.imageDescriptorFromPlugin; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; + +public final class CommonImages +{ + public static final ImageDescriptor DESC_OVERLAY_ERROR + = imageDescriptorFromPlugin( PLUGIN_ID, "images/overlays/error.gif" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_OVERLAY_WARNING + = imageDescriptorFromPlugin( PLUGIN_ID, "images/overlays/warning.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_ADD + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/add.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_EDIT + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/edit.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_DELETE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/delete.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_MOVE_UP + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/move-up.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_MOVE_DOWN + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/move-down.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_EXPAND_ALL + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/expand-all.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_COLLAPSE_ALL + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/collapse-all.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_RESTORE_DEFAULTS + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/restore-defaults.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_BROWSE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/browse.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_BROWSE_MINI + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/browse-mini.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_SELECT_ALL + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/select-all.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_BUTTON_DESELECT_ALL + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/deselect-all.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_OBJECT_FILE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/file.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_OBJECT_FOLDER + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/folder.png" ); //$NON-NLS-1$ + + public static final ImageDescriptor DESC_OBJECT_PACKAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/package.png" ); //$NON-NLS-1$ + + private static Map<ImageDescriptor,Image> cache = new HashMap<ImageDescriptor,Image>(); + + public static ImageDescriptor ADD_CONNECTION_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/add-connection.gif" ); //$NON-NLS-1$ + + public static ImageDescriptor RECONNECT_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/buttons/reconnect.png" ); //$NON-NLS-1$ + + public static ImageDescriptor TABLE_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/table.gif" ); //$NON-NLS-1$ + + public static ImageDescriptor TABLE_OBJ_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/table_obj.gif" ); //$NON-NLS-1$ + + public static ImageDescriptor COLUMN_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/column.gif" ); //$NON-NLS-1$ + + public static ImageDescriptor COLUMN_KEY_IMAGE + = imageDescriptorFromPlugin( PLUGIN_ID, "images/objects/columnKey.gif" ); //$NON-NLS-1$ + + public static Image createImage( final ImageDescriptor descriptor ) + { + synchronized( cache ) + { + Image image = cache.get( descriptor ); + + if( image == null ) + { + image = descriptor.createImage(); + cache.put( descriptor, image ); + } + + return image; + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java new file mode 100644 index 0000000000..301487752b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/TestJunk.java @@ -0,0 +1,59 @@ +package org.eclipse.jpt.ui; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.PersistentType; +import org.eclipse.jpt.core.context.persistence.ClassRef; +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.GenericRootContextNode; + +public class TestJunk { + +// public static List<PersistentType> entities(JpaProject jpaProject) { +// List<PersistentType> entities = new ArrayList<PersistentType>(); +// //this is a place where our provisional api needs to change, I +// //had to cast to an internal class. +// +// //You'll want null checks in here in cases of persistence.xml +// //file not being complete +// //Also, we only support 1 persistenceUnit in the implementation, +// //you should verify there is at least one +// PersistenceUnit persistenceUnit = +// rootContext.persistenceXml().getPersistence().persistenceUnits().next(); +// +// for (Iterator<ClassRef> classRefs = persistenceUnit.classRefs(); +// classRefs.hasNext();) { +// ClassRef classRef = classRefs.next(); +// if (classRef.getJavaPersistentType() != null) { //null if +//// there is no java class with this name) +// if (classRef.getJavaPersistentType().mappingKey() == +// MappingKeys.ENTITY_TYPE_MAPPING_KEY) { +// entities.add(classRef.getJavaPersistentType()); +// } +// } +// } +// //to get entities from orm.xml files +//// for (Iterator<MappingFileRef> mappingFiles = +//// persistenceUnit.mappingFileRefs(); mappingFiles.hasNext();) { +//// MappingFileRef mappingFileRef = mappingFiles.next(); +//// //null checks needed here for OrmXml as well as EntityMappings +//// EntityMappings entityMappings = +//// mappingFileRef.getOrmXml().getEntityMappings(); +//// for (Iterator<OrmPersistentType> persistentTypes = +//// entityMappings.ormPersistentTypes(); persistentTypes.hasNext();) { +//// OrmPersistentType ormPersistentType = +//// persistentTypes.next(); +//// if (ormPersistentType.mappingKey() == +//// MappingKeys.ENTITY_TYPE_MAPPING_KEY) { +//// entities.add(ormPersistentType); +//// } +//// } +//// } +// +// return entities; +// } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java index 20bd1c2bfe..4b024f655c 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/BaseJpaPlatformUi.java @@ -284,7 +284,8 @@ public abstract class BaseJpaPlatformUi // ********** entity generation ********** public void generateEntities(JpaProject project, IStructuredSelection selection) { - EntitiesGenerator.generate(project, selection); + //EntitiesGenerator.generate(project, selection); + EntitiesGenerator2.generate(project, selection); } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java new file mode 100644 index 0000000000..5eb9f0eddd --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator2.java @@ -0,0 +1,236 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.ui.internal.platform.base; + +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.ui.internal.JptUiMessages; +import org.eclipse.jpt.ui.internal.wizards.gen.GenerateEntitiesFromSchemaWizard; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** + * EntitiesGenerator + */ +public class EntitiesGenerator2 { + private JpaProject project; + private IStructuredSelection selection; + + public static void generate(JpaProject project, IStructuredSelection selection) { + new EntitiesGenerator2(project, selection).generate(); + } + + private EntitiesGenerator2(JpaProject project, IStructuredSelection selection) { + super(); + if (project == null) { + throw new NullPointerException(); + } + this.project = project; + this.selection = selection; + } + + + // ********** generate ********** + + /** + * prompt the user with a wizard; + * schedule a job to generate the entities; + * optionally schedule a job to synchronize persistence.xml to + * run afterwards + */ + protected void generate() { + GenerateEntitiesFromSchemaWizard wizard = new GenerateEntitiesFromSchemaWizard(this.project, this.selection); + WizardDialog dialog = new WizardDialog(this.getCurrentShell(), wizard); + dialog.create(); + int returnCode = dialog.open(); + if (returnCode != Window.OK) { + return; + } + //Entities generation happens in the GenerateEntitiesFromSchemaWizard.performFinish() + //method + } + + private Shell getCurrentShell() { + return Display.getCurrent().getActiveShell(); + } + + // ********** overwrite confirmer ********** + + static class OverwriteConfirmer implements org.eclipse.jpt.gen.internal2.OverwriteConfirmer { + private Shell shell; + private boolean overwriteAll = false; + private boolean skipAll = false; + + OverwriteConfirmer(Shell shell) { + super(); + this.shell = shell; + } + + public boolean overwrite(final String className) { + if (this.overwriteAll) { + return true; + } + if (this.skipAll) { + return false; + } + return this.promptUser(className); + } + + private boolean promptUser(String className) { + final OverwriteConfirmerDialog dialog = new OverwriteConfirmerDialog(this.shell, className); + // get on the UI thread synchronously, need feedback before continuing + this.shell.getDisplay().syncExec(new Runnable() { + public void run() { + dialog.open(); + } + }); + if (dialog.getReturnCode() == Window.CANCEL) { + throw new OperationCanceledException(); + } + if (dialog.yes()) { + return true; + } + if (dialog.yesToAll()) { + this.overwriteAll = true; + return true; + } + if (dialog.no()) { + return false; + } + if (dialog.noToAll()) { + this.skipAll = true; + return false; + } + throw new IllegalStateException(); + } + + } + + + // ********** overwrite dialog ********** + + static class OverwriteConfirmerDialog extends Dialog { + private final String className; + private boolean yes = false; + private boolean yesToAll = false; + private boolean no = false; + private boolean noToAll = false; + + OverwriteConfirmerDialog(Shell parent, String className) { + super(parent); + this.className = className; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText(JptUiMessages.OverwriteConfirmerDialog_title); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + GridLayout gridLayout = (GridLayout) composite.getLayout(); + gridLayout.numColumns = 2; + + Label text = new Label(composite, SWT.LEFT); + text.setText(NLS.bind(JptUiMessages.OverwriteConfirmerDialog_text, this.className)); + text.setLayoutData(new GridData()); + + return composite; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + this.createButton(parent, IDialogConstants.YES_ID, IDialogConstants.YES_LABEL, false); + this.createButton(parent, IDialogConstants.YES_TO_ALL_ID, IDialogConstants.YES_TO_ALL_LABEL, false); + this.createButton(parent, IDialogConstants.NO_ID, IDialogConstants.NO_LABEL, true); + this.createButton(parent, IDialogConstants.NO_TO_ALL_ID, IDialogConstants.NO_TO_ALL_LABEL, false); + this.createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + @Override + protected void buttonPressed(int buttonId) { + switch (buttonId) { + case IDialogConstants.YES_ID : + this.yesPressed(); + break; + case IDialogConstants.YES_TO_ALL_ID : + this.yesToAllPressed(); + break; + case IDialogConstants.NO_ID : + this.noPressed(); + break; + case IDialogConstants.NO_TO_ALL_ID : + this.noToAllPressed(); + break; + case IDialogConstants.CANCEL_ID : + this.cancelPressed(); + break; + default : + break; + } + } + + private void yesPressed() { + this.yes = true; + this.setReturnCode(OK); + this.close(); + } + + private void yesToAllPressed() { + this.yesToAll = true; + this.setReturnCode(OK); + this.close(); + } + + private void noPressed() { + this.no = true; + this.setReturnCode(OK); + this.close(); + } + + private void noToAllPressed() { + this.noToAll = true; + this.setReturnCode(OK); + this.close(); + } + + boolean yes() { + return this.yes; + } + + boolean yesToAll() { + return this.yesToAll; + } + + boolean no() { + return this.no; + } + + boolean noToAll() { + return this.noToAll; + } + } + + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java new file mode 100644 index 0000000000..7c3ecba423 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationFigure.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.draw2d.Button; +import org.eclipse.draw2d.ChopboxAnchor; +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.draw2d.ConnectionEndpointLocator; +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.Label; +import org.eclipse.draw2d.LineBorder; +import org.eclipse.draw2d.PolygonDecoration; +import org.eclipse.draw2d.PolylineConnection; +import org.eclipse.draw2d.XYLayout; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; + + +class AssociationFigure extends Button { + + Color enabledColor = new Color( null, 14,66,115); + Color disabledLineColor = new Color( null, 192,215,231); + Color selectedColor = new Color( null, 232,232,232 ); + + Color selectedBorderColor = new Color( null, 14,66,115 ); + LineBorder selectedBorder = new LineBorder( selectedBorderColor, 2 ); + LineBorder unselectedBorder = new LineBorder( ColorConstants.lightGray, 1 ); + Font descriptionFont = new Font(null, "Arial", 8, SWT.NONE); + + /** + * The model behind the the view object + */ + Association association; + TableFigure tableFig1; + TableFigure tableFig2; + PolylineConnection connection ; + + PolygonDecoration referrerDecoration ; + PolygonDecoration referencedDecoration ; + + Label referencedLabel ; + Label referrerLabel ; + Label descriptionLabel ; + + AssociationFigure(Association association) { + this.association = association; + + XYLayout contentsLayout = new XYLayout(); + setLayoutManager(contentsLayout); + setBorder( unselectedBorder ); + + //Create the figures for referrer table and referenced table + tableFig1 = new TableFigure( association.getReferrerTable().getName() ); + tableFig2 = new TableFigure( association.getReferencedTable().getName() ); + + contentsLayout.setConstraint(tableFig1, new Rectangle(10,10,150,20)); + contentsLayout.setConstraint(tableFig2, new Rectangle(280, 10, 150, 20)); + + connection = drawConnection(tableFig1, tableFig2); + + add(tableFig1); + add(tableFig2); + add(connection); + + + descriptionLabel = new Label(""); + contentsLayout.setConstraint(descriptionLabel, new Rectangle(10,30,-1,-1)); + descriptionLabel.setFont( descriptionFont ); + add(descriptionLabel); + + //set white background + this.setBackgroundColor(ColorConstants.white); + + update(); + + } + + private PolylineConnection drawConnection(TableFigure tableFig1, + TableFigure tableFig2) { + /* Creating the connection */ + PolylineConnection connection = new PolylineConnection(); + ChopboxAnchor sourceAnchor = new ChopboxAnchor(tableFig1); + ChopboxAnchor targetAnchor = new ChopboxAnchor(tableFig2); + connection.setSourceAnchor(sourceAnchor); + connection.setTargetAnchor(targetAnchor); + + /* Creating the decoration */ + referrerDecoration = new SmoothPolygonDecoration(); + connection.setSourceDecoration(referrerDecoration); + + referencedDecoration = new SmoothPolygonDecoration(); + connection.setTargetDecoration(referencedDecoration); + + + /* Adding labels to the connection */ + ConnectionEndpointLocator sourceEndpointLocator = + new ConnectionEndpointLocator(connection, false); + sourceEndpointLocator.setVDistance(-5); + referrerLabel = new Label(""); + connection.add(referrerLabel, sourceEndpointLocator); + + ConnectionEndpointLocator targetEndpointLocator = + new ConnectionEndpointLocator(connection, true); + targetEndpointLocator.setVDistance(-5); + referencedLabel = new Label(""); + connection.add(referencedLabel, targetEndpointLocator); + + ConnectionEndpointLocator relationshipLocator = + new ConnectionEndpointLocator(connection,true); + relationshipLocator.setUDistance(10); + relationshipLocator.setVDistance(-20); + Label relationshipLabel = new Label("contains"); + connection.add(relationshipLabel,relationshipLocator); + return connection; + } + + public Association getAssociation() { + return this.association; + } + + public void setSelected ( boolean isSelected ){ + this.setBackgroundColor( isSelected ? selectedColor : ColorConstants.white ); + this.setBorder(isSelected? selectedBorder : unselectedBorder); + } + + /** + * Update the view with the changes user made on the model + */ + public void update(){ + boolean isGenerated = association.isGenerated(); + + connection.setForegroundColor( isGenerated? enabledColor: disabledLineColor ); + + tableFig1.setEnabled(isGenerated); + tableFig2.setEnabled(isGenerated); + descriptionLabel.setForegroundColor(isGenerated? enabledColor: disabledLineColor); + + //paintDirectionalityAndCardinality + String cardinalityStr; + String directionality = association.getDirectionality(); + String cardinality = association.getCardinality(); + //Draw referrerRole + if (cardinality.equals(Association.MANY_TO_ONE) || cardinality.equals(Association.MANY_TO_MANY)) { + cardinalityStr = "*"; + } else { + cardinalityStr = "1"; + } + if (directionality.equals(Association.BI_DI) || directionality.equals(Association.OPPOSITE_DI)) { + connection.setSourceDecoration(this.referrerDecoration); + }else{ + connection.setSourceDecoration(null); + } + + this.referrerLabel.setText( cardinalityStr ); + + //Draw referencedRole + if (cardinality.equals(Association.MANY_TO_ONE) || cardinality.equals(Association.ONE_TO_ONE)) { + cardinalityStr = "1"; + } else { + cardinalityStr = "*"; + } + if (directionality.equals(Association.BI_DI) || directionality.equals(Association.NORMAL_DI)) { + connection.setTargetDecoration(this.referencedDecoration); + }else{ + connection.setTargetDecoration(null); + } + this.referencedLabel.setText(cardinalityStr); + + String text = ""; + String referrerTableName = association.getReferrerTableName(); + String referencedTable = association.getReferencedTableName(); + if( cardinality.equals(Association.MANY_TO_ONE ) ){ + text = String.format( JptUiEntityGenMessages.manyToOneDesc, referencedTable , referrerTableName ); + }else if( cardinality.equals(Association.ONE_TO_ONE ) ){ + text = String.format( JptUiEntityGenMessages.oneToOneDesc, referrerTableName, referencedTable ); + }else if( cardinality.equals(Association.MANY_TO_MANY) ){ + text = String.format( JptUiEntityGenMessages.manyToManyDesc, referrerTableName, referencedTable, referencedTable, referrerTableName ); + } + + if( association.isCustom() ){ + connection.setLineStyle( SWT.LINE_DOT); + } + + this.descriptionLabel.setText(text); + + } + + public class SmoothPolygonDecoration extends PolygonDecoration + { + public SmoothPolygonDecoration() + { + super(); + } + + @Override + public void paintFigure(Graphics graphics) + { + int savedAntialias = graphics.getAntialias(); + graphics.setAntialias(SWT.ON); + super.paintFigure(graphics); + graphics.setAntialias(savedAntialias); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java new file mode 100644 index 0000000000..e4d690d27f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationTablesPage.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createButton; +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createLabel; +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.createText; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; + + + +public class AssociationTablesPage extends NewAssociationWizardPage { + + private Button simpleAssoBtn; + private Button mtmAssoBtn; + private Text table1TextField ; + private Text table2TextField ; + private Text joinTableTextField; + private Button joinTableBrowse; + + public AssociationTablesPage(ORMGenCustomizer customizer) { + super(customizer, "AssociationTablesPage"); + setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_title); + setDescription(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_desc); + } + + public void createControl(Composite composite) { + initializeDialogUnits(composite); + Composite parent = new Composite(composite, SWT.NONE); + parent.setLayout(new GridLayout(1, true)); + + Group assocKindGroup = new Group(parent, SWT.NULL); + int nColumns= 3 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + assocKindGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + assocKindGroup.setLayout(layout); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES); + assocKindGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocKind); + + simpleAssoBtn = createButton(assocKindGroup, 3, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc, SWT.RADIO); + mtmAssoBtn = createButton(assocKindGroup, 3, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc, SWT.RADIO); + + + Group assocTablesGroup = new Group(parent, SWT.NULL); + nColumns= 3 ; + layout = new GridLayout(); + layout.numColumns = nColumns; + assocTablesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + assocTablesGroup.setLayout(layout); + + + assocTablesGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocTables ); + + createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_table1); + table1TextField = createText(assocTablesGroup, 1); + + Button browser1 = createButton(assocTablesGroup, 1, "", SWT.NONE); + browser1.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); + + browser1.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getTableNames() ); + if( dlg.open() ==Dialog.OK ){ + table1TextField.setText( dlg.getSelectedTable() ); + getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_REFERRER_TABLE, table1TextField.getText()); + getWizard().getContainer().updateButtons(); + ((NewAssociationWizard)getWizard()).updateTableNames(); + } + } + }); + + createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_table2); + table2TextField = createText(assocTablesGroup, 1); + + Button browser2 = createButton(assocTablesGroup, 1, "", SWT.NONE); + browser2.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); + + browser2.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getSchema() ); + if( dlg.open() == Dialog.OK){ + table2TextField.setText( dlg.getSelectedTable() ); + getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_REFERENCED_TABLE, table2TextField.getText()); + ((NewAssociationWizard)getWizard()).updateTableNames(); + } + updatePageComplete(); + } + }); + + createLabel(assocTablesGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_tablesPage_assocTables ); + joinTableTextField = createText(assocTablesGroup, 1); + joinTableTextField.setEnabled(false); + + joinTableBrowse = createButton(assocTablesGroup, 1, "", SWT.NONE); + joinTableBrowse.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE )); + joinTableBrowse.setEnabled(false); + + joinTableBrowse.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + SelectTableDialog dlg = new SelectTableDialog( Display.getDefault().getActiveShell(), customizer.getSchema() ); + if( dlg.open() == Dialog.OK){ + joinTableTextField.setText( dlg.getSelectedTable() ); + getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_JOIN_TABLE, joinTableTextField.getText() ); + ((NewAssociationWizard)getWizard()).updateTableNames(); + getWizard().getContainer().updateButtons(); + } + updatePageComplete(); + } + }); + + setControl(parent); + + simpleAssoBtn.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + joinTableTextField.setEnabled(false); + joinTableTextField.clearSelection(); + joinTableTextField.setText(""); + joinTableBrowse.setEnabled(false); + getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE); + getWizardDataModel().remove( NewAssociationWizard.ASSOCIATION_JOIN_TABLE ); + ((NewAssociationWizard)getWizard()).updateTableNames(); + updatePageComplete(); + } + + }); + + mtmAssoBtn.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + joinTableTextField.setEnabled(true); + joinTableBrowse.setEnabled(true); + getWizardDataModel().put( NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_MANY); + ((NewAssociationWizard)getWizard()).updateTableNames(); + updatePageComplete(); + } + }); + + this.setPageComplete( false); + table1TextField.setFocus(); + } + + public boolean canFlipToNextPage() { + return isPageComplete(); + } + + public void updatePageComplete() { + if( this.table1TextField.getText().length() <= 0){ + setPageComplete(false); + return; + } + if( mtmAssoBtn.getSelection() ){ + if( this.joinTableTextField.getText().length() <= 0 ){ + setPageComplete(false); + return; + } + } + setPageComplete(true); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java new file mode 100644 index 0000000000..ca06c33c32 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/AssociationsListComposite.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.List; + +import org.eclipse.draw2d.ActionEvent; +import org.eclipse.draw2d.ActionListener; +import org.eclipse.draw2d.Figure; +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.draw2d.LineBorder; +import org.eclipse.draw2d.ToolbarLayout; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; + +/** + * A Draw2d figure representing list of associations between two database tables + * + */ +public class AssociationsListComposite extends FigureCanvas { + + List<Association> associations; + AssociationToggleSelectionListener listener ; + TableAssociationsWizardPage tableAssociationsWizardPage; //the parent wizard page + AssociationFigure selectedAssociationFigure ; + + public AssociationsListComposite(Composite parent, TableAssociationsWizardPage tableAssociationsWizardPage){ + super(parent); + this.tableAssociationsWizardPage = tableAssociationsWizardPage; + + setBounds(10, 10 , 500, 200); + setBackground( new Color(Display.getDefault(), 255,255,255)); + + Figure figure = new Figure(); + figure.setLayoutManager(new ToolbarLayout()); + figure.setBorder(new LineBorder(1)); + this.listener = new AssociationToggleSelectionListener(); + + this.setContents(figure); + } + + @SuppressWarnings("unchecked") + public void updateAssociations(List<Association> associations){ + Figure figure = (Figure)this.getContents(); + List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren(); + for(AssociationFigure assocFig : associationFigures){ + assocFig.removeActionListener(listener); + } + figure.removeAll(); + this.selectedAssociationFigure = null; + + this.associations = associations; + if( associations != null ){ + for( int i = 0; i <associations.size(); i ++ ){ + Association association = associations.get(i); + //Hide the association from individual table to MTM tables + if( !association.isCustom() && !association.isGenerated()){ + continue; + } + AssociationFigure assocFigure = new AssociationFigure(associations.get(i)); + assocFigure.addActionListener( listener ); + figure.add(assocFigure); + } + } + } + + public Association getSelectedAssociation(){ + return this.selectedAssociationFigure.getAssociation(); + } + + @SuppressWarnings("unchecked") + public void updateSelectedAssociation(){ + Figure figure = (Figure)this.getContents(); + List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren(); + for(AssociationFigure assocFig : associationFigures){ + if( assocFig == this.selectedAssociationFigure){ + assocFig.update(); + } + } + } + + /** + * Get the association just before the selected one in UI + * @return + */ + @SuppressWarnings("unchecked") + public Association getPreviousAssociation(){ + Figure figure = (Figure)this.getContents(); + List<AssociationFigure> associationFigures = (List<AssociationFigure>) figure.getChildren(); + AssociationFigure ret = null; + for(AssociationFigure assocFig : associationFigures){ + if( assocFig.isSelected() ){ + break; + } + ret = assocFig; + } + return ret==null?null:ret.getAssociation(); + } + + class AssociationToggleSelectionListener implements ActionListener { + public void actionPerformed(ActionEvent event) { + AssociationFigure figure = (AssociationFigure )event.getSource() ; + figure.setSelected(true); + Association association = figure.getAssociation(); + tableAssociationsWizardPage.updateAssociationEditPanel(association); + //un-select the previous selected + if( selectedAssociationFigure != null && selectedAssociationFigure!= figure ){ + selectedAssociationFigure.setSelected( false ); + } + //Highlight new selection + selectedAssociationFigure = figure; + selectedAssociationFigure.setSelected( true ); + + } + + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java new file mode 100644 index 0000000000..af682182b0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CardinalityPage.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + +public class CardinalityPage extends NewAssociationWizardPage { + + private Label mtoDescLabel; + private Label otmDescLabel; + private Label otoDescLabel; + private Label mtmDescLabel; + + private Button[] cardinalityButtons = new Button[4]; + + protected CardinalityPage(ORMGenCustomizer customizer) { + super( customizer , "CardinalityPage" ); + setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_cardinalityPage_title); + setDescription( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_cardinalityPage_desc); + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 1 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES); + + CardinalitySelectionListener selectionListener = new CardinalitySelectionListener(); + cardinalityButtons[0] = createRadioButton( composite, 1, JptUiEntityGenMessages.manyToOne); + cardinalityButtons[0].addSelectionListener( selectionListener ); + //Default cardinality is MTO + cardinalityButtons[0].setSelection(true); + getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE); + + mtoDescLabel = createLabel(composite,1, JptUiEntityGenMessages.manyToOneDesc); + + cardinalityButtons[1] = createRadioButton( composite, 1, JptUiEntityGenMessages.oneToMany); + cardinalityButtons[1].addSelectionListener( selectionListener ); + + otmDescLabel = createLabel(composite,1, JptUiEntityGenMessages.manyToOneDesc); + + cardinalityButtons[2] = createRadioButton( composite, 1, JptUiEntityGenMessages.oneToOne); + cardinalityButtons[2].addSelectionListener( selectionListener ); + + otoDescLabel = createLabel(composite,1, JptUiEntityGenMessages.oneToOneDesc); + + cardinalityButtons[3] = createRadioButton( composite, 1, JptUiEntityGenMessages.manyToMany); + mtmDescLabel= createLabel(composite,1, JptUiEntityGenMessages.manyToManyDesc); + + setControl(composite); + this.setPageComplete( true ); + + cardinalityButtons[0].setFocus(); + + } + + public void updateWithNewTables() { + String s1 = getReferrerTableName() ; + String s2 = getReferencedTableName() ; + String joinTableName = getJoinTableName(); + if( s1 == null || s2 == null ) + return ; + + updateDescriptionText(s1, s2); + if( joinTableName == null ){ + cardinalityButtons[0].setEnabled(true); + cardinalityButtons[1].setEnabled(true); + cardinalityButtons[2].setEnabled(true); + cardinalityButtons[3].setEnabled(false); + mtmDescLabel.setEnabled(false); + }else{ + cardinalityButtons[0].setEnabled(false); + cardinalityButtons[1].setEnabled(false); + cardinalityButtons[2].setEnabled(false); + cardinalityButtons[3].setEnabled(true); + cardinalityButtons[3].setSelection(true); + mtmDescLabel.setEnabled(true); + } + ((Composite)this.getControl()).layout() ; + } + + private void updateDescriptionText(String s1, String s2) { + //MTO + String msg = String.format(JptUiEntityGenMessages.manyToOneDesc, s2, s1); + mtoDescLabel.setText( msg ); + //OTM + msg = String.format(JptUiEntityGenMessages.manyToOneDesc, s1, s2); + otmDescLabel.setText( msg ); + msg = String.format(JptUiEntityGenMessages.oneToOneDesc, s1, s2); + otoDescLabel.setText( msg ); + msg = String.format(JptUiEntityGenMessages.manyToManyDesc, s1, s2, s2, s1); + mtmDescLabel.setText( msg ); + } + + public boolean canFlipToNextPage() { + return false; + } + + private Label createLabel(Composite container, int span, String text) { + Label label = new Label(container, SWT.NONE); + label.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + gd.horizontalIndent = 30; + label.setLayoutData(gd); + return label; + } + + + private Button createRadioButton(Composite container, int span, String text ) { + Button btn = new Button(container, SWT.RADIO ); + btn.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + btn.setLayoutData(gd); + return btn; + } + + + private class CardinalitySelectionListener implements SelectionListener { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + if( e.getSource() == cardinalityButtons[0]){ + getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_ONE); + }else if( e.getSource() == cardinalityButtons[1]){ + getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.ONE_TO_MANY ); + }else if( e.getSource() == cardinalityButtons[2]){ + getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.ONE_TO_ONE); + }else{ + getWizardDataModel().put(NewAssociationWizard.ASSOCIATION_CADINALITY, Association.MANY_TO_MANY); + } + CardinalityPage.this.setPageComplete(true); + + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java new file mode 100644 index 0000000000..e8e76c1373 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/CascadeDialog.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.jpt.gen.internal2.AssociationRole; +import org.eclipse.jpt.gen.internal2.util.StringUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Shell; + +/** + * Simple dialog allows user to set the cascade property of an associationRole. + * The value of cascade can be "all", or any combination of other selections. + * + */ +public class CascadeDialog extends TrayDialog { + + private static String[] ALL_CASCADES = new String[] {TagNames.ALL_CASCADE, TagNames.PERSIST_CASCADE, TagNames.MERGE_CASCADE + , TagNames.REMOVE_CASCADE, TagNames.REFRESH_CASCADE}; + + private static String[] ALL_CASCADES_LABELS + = new String[] { "&all", //$NON-NLS-1$ + "&persist", //$NON-NLS-1$ + "&merge", //$NON-NLS-1$ + "&remove", //$NON-NLS-1$ + "r&efresh"}; //$NON-NLS-1$ + + + private Button[] allButtons = new Button[ALL_CASCADES.length]; + + private AssociationRole associationRole; + private List<String> cascades; + + protected CascadeDialog(Shell parentShell) { + super(parentShell); + } + + public static CascadeDialog create(AssociationRole role) { + CascadeDialog dlg = new CascadeDialog(Display.getDefault().getActiveShell() ); + dlg.setAssociationRole(role); + return dlg; + } + + /* + * (non-Javadoc) Method declared on Window. + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(JptUiEntityGenMessages.selectCascadeDlgTitle); + } + + private void setAssociationRole(AssociationRole role) { + this.associationRole = role; + List<String> list = StringUtil.strToList(associationRole.getCascade(), ',', true/*trim*/); //role.getCascade() contains the comma separed cascades (see below) + if (list == null) { + list = Collections.emptyList(); + } + cascades = list; + + } + + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + protected Control createDialogArea(Composite parent) { + Composite container = (Composite) super.createDialogArea(parent); + createCascadeTypesGroup(container); + Dialog.applyDialogFont(container); + return container; + } + + private void createCascadeTypesGroup(Composite parent) { + Group group = new Group(parent, SWT.NONE); + group.setLayout(new GridLayout()); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = 275; + group.setLayoutData(gd); + group.setText(JptUiEntityGenMessages.cascade); + + for( int i=0; i< ALL_CASCADES.length; i ++ ){ + Button checkbox = new Button(group, SWT.CHECK); + checkbox.setText( ALL_CASCADES_LABELS[i] ); + checkbox.setSelection( isInList(ALL_CASCADES[i]) ); //$NON-NLS-1$ + checkbox.setData(ALL_CASCADES[i]); + allButtons[i] = checkbox; + /*if <code>all</code> is selected then deselect all others*/ + checkbox.addSelectionListener( new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + Button b = (Button)e.getSource(); + if( b.getSelection() ){ + if( b == allButtons[0] ){ + for( Button btn : allButtons ){ + if( btn != e.getSource() ) btn.setSelection(false); + } + }else{ + allButtons[0].setSelection(false); + } + } + } + }); + } + } + + protected void okPressed() { + StringBuilder builder = new StringBuilder(); + for( Button b : allButtons ){ + if( b.getSelection() ){ + if( builder.length()>0 ){ + builder.append( ','); + } + builder.append( b.getData() ); + } + } + this.associationRole.setCascade( builder.toString() ); + super.okPressed(); + } + + private boolean isInList(String cascade) { + for( String s : cascades ){ + if( s.equals(cascade )){ + return true; + } + } + return false; + } + +} + +class TagNames +{ + public static final String BASIC_TAG = "basic"; + public static final String CASCADE_TAG = "cascade"; + public static final String COLUMN_TAG = "column"; + public static final String EMBEDDED_TAG = "embedded"; + public static final String EMBEDDED_ID_TAG = "embedded-id"; + public static final String GENERATED_VALUE_TAG = "generated-value"; + public static final String ID_TAG = "id"; + public static final String ID_CLASS_TAG = "id"; + public static final String JOIN_COLUMN_TAG = "join-column"; + public static final String INVERSE_JOIN_COLUMN_TAG = "inverse-join-column"; + public static final String LOB_TAG = "lob"; + public static final String MANY_TO_MANY_TAG = "many-to-many"; + public static final String MANY_TO_ONE_TAG = "many-to-one"; + public static final String MAPPED_BY_TAG = "mapped-by"; + public static final String ONE_TO_MANY_TAG = "one-to-many"; + public static final String ONE_TO_ONE_TAG = "one-to-one"; + public static final String PK_JOIN_COLUMN_TAG = "primary-key-join-column"; + public static final String TABLE_TAG = "table"; + public static final String VERSION_TAG = "version"; + public static final String JOIN_TABLE_TAG = "join-table"; + + /*cascade tags*/ + public static final String ALL_CASCADE = "all"; + public static final String PERSIST_CASCADE = "persist"; + public static final String MERGE_CASCADE = "merge"; + public static final String REMOVE_CASCADE = "remove"; + public static final String REFRESH_CASCADE = "refresh"; +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java new file mode 100644 index 0000000000..478449671c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/ColumnGenPanel.java @@ -0,0 +1,353 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.JavaConventions; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.gen.internal2.ORMGenColumn; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; + +/** + * The panel used in the <code>TablesAndColumnsPage</code> wizard page + * to edit the column generation properties. + * An instance of this class is created by the <code>ORMGenWizard</code> + * implementation. + + */ +public class ColumnGenPanel +{ + WizardPage wizardPage ; + Composite parent; //parent control with grid layout + int columns; //total columns in the parent composite + + ORMGenCustomizer customizer; + + private ORMGenColumn mColumn; + private boolean mPanelInited; + private boolean mIsUpdatingControls; + + private Group columnMappingGroup; + private Button mGeneratedCheckbox; + private Text mPropNameField; + private Combo mMappingKindCombo; + private Combo mPropTypeCombo; + private Button mUpdateableCheckBox; + private Button mInsertableCheckBox; + + private Group domainClassGroup ; + private ScopePanel mPropGetScopePanel; + private ScopePanel mPropSetScopePanel; + + public ColumnGenPanel(Composite parent, int columns, ORMGenCustomizer customizer, WizardPage wizardPage ) { + this.wizardPage = wizardPage; + this.customizer = customizer; + this.parent =parent; + this.columns = columns; + + initPanel(); + } + /** + * Changes the table edited by the panel. + * This is supposed to update the panel editing controls + * using the column values. + */ + public void setColumn(ORMGenColumn column) { + mColumn = column; + + /*lazy init panel because it uses mColumn*/ + if (!mPanelInited) { + initPanel(); + mPanelInited = true; + } + + updateControls(); + } + private void updateControls() { + if (mIsUpdatingControls) { + return; + } + + mIsUpdatingControls = true; + boolean isGenerated = mColumn.isGenerated(); + mGeneratedCheckbox.setSelection( isGenerated); + + enableControls(isGenerated); + try { + mPropNameField.setText(mColumn.getPropertyName()); + + mPropTypeCombo.setText( mColumn.getPropertyType()); + + mMappingKindCombo.setText( mColumn.getMappingKind()); + + mUpdateableCheckBox.setSelection( mColumn.isUpdateable()); + + mInsertableCheckBox.setSelection(mColumn.isInsertable()); + + mPropGetScopePanel.enableComponents(isGenerated); + mPropGetScopePanel.setScope(mColumn.getPropertyGetScope()); + + mPropSetScopePanel.enableComponents( isGenerated ); + mPropSetScopePanel.setScope(mColumn.getPropertySetScope()); + } catch (Exception e) { + JptUiPlugin.log(e); + } + + mIsUpdatingControls = false; + } + private void enableControls(boolean isGenerated) { + Control[] controls = this.domainClassGroup.getChildren(); + for( Control c: controls){ + c.setEnabled( isGenerated ); + } + + controls = this.columnMappingGroup.getChildren(); + for( Control c: controls){ + c.setEnabled( isGenerated ); + } + } + /** + * Initializes the panel by adding the editing controls. + * @param columns + * @param parent + */ + protected void initPanel() { + createControls(parent, columns); + this.mPanelInited = true; + } + + //------------------------------------------- + //----- ScopePanel class -------------------- + //------------------------------------------- + /** + * A panel containing 3 radios (public, protected, private) + */ + private class ScopePanel + { + private Button mPublicRadio; + private Button mProtectedRadio; + private Button mPrivateRadio; + + public ScopePanel(Composite comp, SelectionListener listener) { + //super(3, 20/*hspacing*/, 0/*vspacing*/); + + Composite radioGroup = new Composite( comp, SWT.NONE); + radioGroup.setLayout(new GridLayout(3, true)); + GridData gd = new GridData(); + gd.horizontalSpan = 3; + radioGroup.setLayoutData(gd); + + /*string not localized intentionally, they are used as the actual + * scope value (see getText() usage)*/ + mPublicRadio = new Button( radioGroup, SWT.RADIO ); + mPublicRadio.setText( "public"); + mPublicRadio.setLayoutData(new GridData()); + mProtectedRadio = new Button( radioGroup, SWT.RADIO ); + mProtectedRadio.setText("protected"); + mProtectedRadio.setLayoutData(new GridData()); + mPrivateRadio = new Button(radioGroup, SWT.RADIO ); + mPrivateRadio.setText( "private"); + mPrivateRadio.setLayoutData(new GridData()); + + mPublicRadio.addSelectionListener(listener); + mProtectedRadio.addSelectionListener(listener); + mPrivateRadio.addSelectionListener(listener); + + } + public void enableComponents(boolean b) { + mPublicRadio.setEnabled(b); + mProtectedRadio.setEnabled(b); + mPrivateRadio.setEnabled(b); + } + /** + * Returns the currently selected scope. + */ + public String getScope() { + Button radio = null; + if (mPublicRadio.getSelection()) { + radio = mPublicRadio; + } else if (mProtectedRadio.getSelection() ) { + radio = mProtectedRadio; + } else if (mPrivateRadio.getSelection() ) { + radio = mPrivateRadio; + } + return radio != null ? radio.getText() : null; + } + public void setScope(String scope) { + mPublicRadio.setSelection(false); + mProtectedRadio.setSelection(false); + mPrivateRadio.setSelection(false); + if( scope == null ) + return; + if (scope.equals(ORMGenColumn.PUBLIC_SCOPE)) { + mPublicRadio.setSelection(true); + } else if (scope.equals(ORMGenColumn.PROTECTED_SCOPE)) { + mProtectedRadio.setSelection(true); + } else if (scope.equals(ORMGenColumn.PRIVATE_SCOPE)) { + mPrivateRadio.setSelection(true); + } + } + } + + //------------------------------------------- + //----- private methods --------------------- + //------------------------------------------- + private void createControls(Composite composite, int columns) { + mGeneratedCheckbox = new Button(composite, SWT.CHECK); + mGeneratedCheckbox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_genProp); + mGeneratedCheckbox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + mColumn.setGenerated(mGeneratedCheckbox.getSelection() ); + updateControls(); + } + }}); + SWTUtil.fillColumns(mGeneratedCheckbox, columns); + + columnMappingGroup = new Group( composite, SWT.NONE); + columnMappingGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colMapping); + columnMappingGroup.setLayout(new GridLayout(columns, false)); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + layoutData.horizontalIndent = 20 ; + columnMappingGroup.setLayoutData(layoutData); + + SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_propName ); + mPropNameField = new Text(columnMappingGroup, SWT.BORDER | SWT.SINGLE ); + mPropNameField.addModifyListener(new ModifyListener(){ + @SuppressWarnings("restriction") + public void modifyText(ModifyEvent e) { + if (!mIsUpdatingControls) { + String fldName = mPropNameField.getText(); + IStatus status = JavaConventions.validateIdentifier( fldName, + CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3 ); + if( !status.matches(IStatus.ERROR)){ + mColumn.setPropertyName(fldName); + wizardPage.setErrorMessage(null); + }else{ + wizardPage.setErrorMessage(status.getMessage()); + } + } + } + }); + SWTUtil.fillColumns(mPropNameField ,3); + + SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_propType ); + mPropTypeCombo = new Combo(columnMappingGroup, SWT.SINGLE | SWT.READ_ONLY); + mPropTypeCombo.setItems( this.customizer.getAllPropertyTypes()); + mPropTypeCombo.addModifyListener( new ModifyListener(){ + public void modifyText(ModifyEvent e) { + if (!mIsUpdatingControls) { + mColumn.setPropertyType(mPropTypeCombo.getText()); + } + } + }); + SWTUtil.fillColumns(mPropTypeCombo,3); + + SWTUtil.createLabel(columnMappingGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_mapKind ); + mMappingKindCombo = new Combo(columnMappingGroup, SWT.SINGLE | SWT.READ_ONLY); + mMappingKindCombo.setItems( this.customizer.getAllMappingKinds()); + mMappingKindCombo.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + mColumn.setMappingKind((String)mMappingKindCombo.getText()); + } + + }}); + SWTUtil.fillColumns(mMappingKindCombo ,3); + + mUpdateableCheckBox = new Button(columnMappingGroup, SWT.CHECK); + mUpdateableCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colUpdateable); + mUpdateableCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + mColumn.setUpdateable(mUpdateableCheckBox.getSelection() ); + } + }}); + SWTUtil.fillColumns(mUpdateableCheckBox ,4); + + mInsertableCheckBox = new Button(columnMappingGroup, SWT.CHECK); + mInsertableCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_colInsertable); + mInsertableCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + mColumn.setInsertable(mInsertableCheckBox.getSelection()); + } + }}); + SWTUtil.fillColumns(mInsertableCheckBox ,4); + + SWTUtil.createLabel(composite, 4,""); + + createJavaBeanPropertyControls(composite, columns); + } + + void createJavaBeanPropertyControls(Composite composite, int columns){ + //Java class generation properties + domainClassGroup = new Group(composite, SWT.NONE); + domainClassGroup.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_beanProp ); + domainClassGroup.setLayout(new GridLayout(columns, false)); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + layoutData.horizontalIndent = 20; + domainClassGroup.setLayoutData(layoutData); + + SWTUtil.createLabel(domainClassGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_getterScope ); + mPropGetScopePanel = new ScopePanel(domainClassGroup, new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + if( ((Button)e.getSource()).getSelection() ) + mColumn.setPropertyGetScope(mPropGetScopePanel.getScope()); + } + + }}); + + SWTUtil.createLabel(domainClassGroup, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_colPanel_setterScope ); + mPropSetScopePanel = new ScopePanel(domainClassGroup, new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + if (!mIsUpdatingControls) { + if( ((Button)e.getSource()).getSelection() ) + mColumn.setPropertySetScope(mPropSetScopePanel.getScope()); + } + }}); + + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java new file mode 100644 index 0000000000..3a52beeba1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DatabaseGroup.java @@ -0,0 +1,521 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.EventListener; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.SortedSet; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.db.ConnectionAdapter; +import org.eclipse.jpt.db.ConnectionListener; +import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.JptDbPlugin; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.SchemaContainer; +import org.eclipse.jpt.db.ui.internal.DTPUiTools; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; + +/** + * A composite used to connect to database, includes following UI controls: + * - connection combo-box + * - schema combo-box + * - add connection button + * - reconnect button + */ +public class DatabaseGroup +{ + private final JpaProject jpaProject; + private final Set<Listener> listeners = Collections.synchronizedSet(new HashSet<Listener>()); + + // these are kept in synch with the selection + private ConnectionProfile selectedConnectionProfile; + private Schema selectedSchema; + + private final Combo connectionComboBox; + + private final Combo schemaComboBox; + + private final Button reconnectButton; + + private final ConnectionListener connectionListener; + + private IWizardContainer wizardContainer; + + // ********** construction ********** + + DatabaseGroup(IWizardContainer wizardContainer, JpaProject jpaProject, Composite parent, int widthHint) + { + super(); + this.wizardContainer = wizardContainer; + this.jpaProject = jpaProject; + + // connection combo-box + this.buildLabel(parent, 1, JptUiEntityGenMessages.connection); + this.connectionComboBox = this.buildComboBox(parent, widthHint, this.buildConnectionComboBoxSelectionListener()); + + // add connection button + this.buildButton(parent, JptUiEntityGenMessages.addConnectionLink, CommonImages.createImage( CommonImages.ADD_CONNECTION_IMAGE ), this.buildAddConnectionLinkSelectionListener()); + + // A composite holds the reconnect button & text + this.buildLabel(parent, 1, ""); + Composite comp = new Composite( parent , SWT.NONE ); + GridData gd = new GridData(); + gd.grabExcessHorizontalSpace = true ; + gd.horizontalSpan = 2; + comp.setLayoutData( gd ); + GridLayout gl = new GridLayout(2, false); + // Make the reconnect button to be closer to the connection combo. + gl.marginTop = -5; + comp.setLayout(gl); + this.reconnectButton = this.buildButton(comp, JptUiEntityGenMessages.connectLink, CommonImages.createImage( CommonImages.RECONNECT_IMAGE ), this.buildReconnectLinkSelectionListener()); + this.buildLabel(comp, 1, JptUiEntityGenMessages.schemaInfo); + + // schema combo-box + this.buildLabel(parent, 1, JptUiEntityGenMessages.schema); + this.schemaComboBox = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); + GridData data = new GridData(SWT.BEGINNING, SWT.CENTER, true, false); + data.horizontalAlignment = SWT.FILL; + data.horizontalSpan = 1; + data.grabExcessHorizontalSpace = true ; + this.schemaComboBox.setLayoutData(data); + this.schemaComboBox.addSelectionListener(this.buildSchemaComboBoxSelectionListener()); + // filler + new Label(parent, SWT.NULL); + + this.connectionListener = this.buildConnectionListener(); + } + + + public void init() + { + // initialize state, based on JPA project + this.selectedConnectionProfile = this.getJpaProjectConnectionProfile(); + this.selectedSchema = this.getDefaultSchema(); + + if (this.selectedSchema != null) { + this.fireSchemaChanged(this.selectedSchema); + } + if (this.selectedConnectionProfile != null) { + this.selectedConnectionProfile.addConnectionListener(this.connectionListener); + this.fireConnectionProfileChanged(this.selectedConnectionProfile); + } + + this.updateConnectionComboBox(); + this.updateSchemaComboBox(); + this.updateReconnectLink(); + + } + // ********** intra-wizard methods ********** + + ConnectionProfile getSelectedConnectionProfile() { + return this.selectedConnectionProfile; + } + + Schema getSelectedSchema() { + return this.selectedSchema; + } + + void dispose() { + if (this.selectedConnectionProfile != null) { + this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); + } + } + + + // ********** internal methods ********** + + /** + * this can return null; + * called at start-up and when the selected connection profile changes + */ + private ConnectionProfile getJpaProjectConnectionProfile() { + return this.jpaProject.getConnectionProfile(); + } + + /** + * this can return null; + * called at start-up and when the selected connection profile changes + */ + private Schema getDefaultSchema() { + try{ + return (this.selectedConnectionProfile == this.getJpaProjectConnectionProfile()) ? + jpaProject.getDefaultDbSchema() : null; + }catch(Exception e ){ + e.printStackTrace(); + } + return null; + } + + /** + * the connection combo-box is updated at start-up and when the user + * adds a connection profile + */ + private void updateConnectionComboBox() { + this.connectionComboBox.removeAll(); + for (String cpName : this.buildSortedConnectionProfileNames()) { + this.connectionComboBox.add(cpName); + } + if (this.selectedConnectionProfile != null) { + this.connectionComboBox.select(this.connectionComboBox.indexOf(this.selectedConnectionProfile.getName())); + } + } + + private SortedSet<String> buildSortedConnectionProfileNames() { + return CollectionTools.sortedSet(JptDbPlugin.instance().getConnectionProfileFactory().connectionProfileNames()); + } + + /** + * called at start-up and when the selected connection profile changes + */ + private void updateReconnectLink() { + this.reconnectButton.setEnabled(this.reconnectLinkCanBeEnabled()); + } + + private boolean reconnectLinkCanBeEnabled() { + return (this.selectedConnectionProfile != null) && !(this.selectedConnectionProfile.isActive()); + } + + /** + * the schema combo-box is updated at start-up and + * when the selected connection profile changes + */ + private void updateSchemaComboBox() { + this.schemaComboBox.removeAll(); + for (Iterator<String> stream = this.getSchemata(); stream.hasNext(); ) { + this.schemaComboBox.add(stream.next()); + } + // the current schema *should* be in the current connection profile + if (this.selectedSchema != null) { + this.schemaComboBox.select(this.schemaComboBox.indexOf(this.selectedSchema.getName())); + } + } + + private Iterator<String> getSchemata() { + SchemaContainer sc = jpaProject.getDefaultDbSchemaContainer(); + return (sc == null) ? EmptyIterator.<String>instance() : sc.sortedSchemaIdentifiers(); + } + + /** + * If the specified name matches the name of the JPA project's + * connection profile, return it; otherwise, build a new connection + * profile. + */ + private ConnectionProfile checkJpaProjectConnectionProfile(String cpName) { + ConnectionProfile cp = this.getJpaProjectConnectionProfile(); + if ((cp != null) && cp.getName().equals(cpName)) { + return cp; + } + return this.buildConnectionProfile(cpName); + } + + private ConnectionProfile buildConnectionProfile(String name) { + return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(name); + } + + + // ********** listener callbacks ********** + + void selectedConnectionChanged() { + String text = this.connectionComboBox.getText(); + if (text.length() == 0) { + if (this.selectedConnectionProfile == null) { + return; // no change + } + this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); + this.selectedConnectionProfile = null; + } else { + if (this.selectedConnectionProfile == null) { + this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text); + } else { + if (text.equals(this.selectedConnectionProfile.getName())) { + return; // no change + } + this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); + this.selectedConnectionProfile = this.checkJpaProjectConnectionProfile(text); + } + this.selectedConnectionProfile.addConnectionListener(this.connectionListener); + } + this.fireConnectionProfileChanged(this.selectedConnectionProfile); + this.connectionChanged(); + } + + void selectedSchemaChanged() { + Schema old = this.selectedSchema; + this.selectedSchema = this.selectedConnectionProfile.getDatabase().getSchemaForIdentifier(this.schemaComboBox.getText()); + if (this.selectedSchema != old) { + fireSchemaChanged(this.selectedSchema); + } + } + + /** + * Open the DTP New Connection Profile wizard. + * If the user creates a new connection profile, start using it and + * connect it + */ + void addConnection() { + String addedProfileName = DTPUiTools.createNewConnectionProfile(); + if (addedProfileName == null) { + return; // user pressed "Cancel" + } + if (this.selectedConnectionProfile != null) { + this.selectedConnectionProfile.removeConnectionListener(this.connectionListener); + } + this.selectedConnectionProfile = this.buildConnectionProfile(addedProfileName); + this.selectedConnectionProfile.addConnectionListener(this.connectionListener); + this.updateConnectionComboBox(); + this.selectedConnectionProfile.connect(); + this.updateSchemaComboBox(); + // everything else should be synchronized when we get the resulting open event + this.fireConnectionProfileChanged(this.selectedConnectionProfile); + } + + void reconnect() { + try { + wizardContainer.run(true, true, new IRunnableWithProgress(){ + public void run( final IProgressMonitor monitor ) + throws InvocationTargetException, InterruptedException + { + monitor.beginTask("Connecting to database", 10); + final boolean[] isConnected= new boolean[1]; + isConnected[0]=false; + Thread t= new Thread(){ + public void run() { + selectedConnectionProfile.connect(); + isConnected[0]=true; + } + }; + t.start(); + while( !isConnected[0]){ + Thread.sleep(1000); + monitor.worked(1); + } + // everything should be synchronized when we get the resulting open event + monitor.done(); + } + }); + } catch (Exception e) { + JptUiPlugin.log(e); + } + } + + /** + * called when + * - the user selects a new connection + * - the connection was opened + * - the connection was closed (never happens?) + * we need to update the schema stuff and the reconnect link + */ + void connectionChanged() { + Schema old = this.selectedSchema; + this.selectedSchema = this.getDefaultSchema(); + if (this.selectedSchema != old) { + this.fireSchemaChanged(this.selectedSchema); + } + this.updateSchemaComboBox(); + this.updateReconnectLink(); + } + + + // ********** listeners ********** + + private SelectionListener buildConnectionComboBoxSelectionListener() { + return new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + // nothing special for "default" (double-click?) + this.widgetSelected(event); + } + public void widgetSelected(SelectionEvent event) { + DatabaseGroup.this.selectedConnectionChanged(); + } + @Override + public String toString() { + return "DatabaseConnectionWizardPage connection combo-box selection listener"; //$NON-NLS-1$ + } + }; + } + + private SelectionListener buildSchemaComboBoxSelectionListener() { + return new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + // nothing special for "default" (double-click?) + this.widgetSelected(event); + } + public void widgetSelected(SelectionEvent event) { + DatabaseGroup.this.selectedSchemaChanged(); + } + @Override + public String toString() { + return "DatabaseConnectionWizardPage schema combo-box selection listener"; //$NON-NLS-1$ + } + }; + } + + private SelectionListener buildAddConnectionLinkSelectionListener() { + return new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + DatabaseGroup.this.addConnection(); + } + @Override + public String toString() { + return "DatabaseConnectionWizardPage add connection link selection listener"; //$NON-NLS-1$ + } + }; + } + + private SelectionListener buildReconnectLinkSelectionListener() { + return new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + DatabaseGroup.this.reconnect(); + } + @Override + public String toString() { + return "DatabaseConnectionWizardPage reconnect link selection listener"; //$NON-NLS-1$ + } + }; + } + + private ConnectionListener buildConnectionListener() { + return new ConnectionAdapter() { + @Override + public void opened(ConnectionProfile cp) { + this.connectionChanged(); + } + @Override // this probably won't ever get called... + public void closed(ConnectionProfile cp) { + this.connectionChanged(); + } + private void connectionChanged() { + Display.getDefault().asyncExec( + new Runnable() { + public void run() { + DatabaseGroup.this.connectionChanged(); + } + } + ); + } + @Override + public String toString() { + return "DatabaseConnectionWizardPage connection listener"; //$NON-NLS-1$ + } + }; + } + + + // ********** listeners ********** + + public void addListener(Listener listener) { + if ( ! this.listeners.add(listener)) { + throw new IllegalArgumentException("duplicate listener: " + listener); //$NON-NLS-1$ + } + } + + public void removeListener(Listener listener) { + if ( ! this.listeners.remove(listener)) { + throw new IllegalArgumentException("missing listener: " + listener); //$NON-NLS-1$ + } + } + + private Iterator<Listener> listeners() { + return new CloneIterator<Listener>(this.listeners); + } + + void fireConnectionProfileChanged(ConnectionProfile connectionProfile) { + for (Iterator<Listener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().selectedConnectionProfileChanged(connectionProfile); + } + } + + void fireSchemaChanged(Schema schema) { + for (Iterator<Listener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().selectedSchemaChanged(schema); + } + } + + // ********** UI components ********** + + /** + * build and return a label + */ + private Label buildLabel(Composite parent, int span, String text) { + Label label = new Label(parent, SWT.NONE); + label.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + label.setLayoutData(gd); + return label; + } + + /** + * build and return a combo-box + */ + private Combo buildComboBox(Composite parent, int widthHint, SelectionListener listener) { + Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); + combo.addSelectionListener(listener); + GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); + //data.grabExcessHorizontalSpace = true ; + data.widthHint = widthHint; + combo.setLayoutData(data); + return combo; + } + + /** + * build and return a link + */ + private Button buildButton(Composite parent, String toolTipText, Image image, SelectionListener listener) { + Button button = new Button(parent, SWT.NONE); + GridData data = new GridData(GridData.END, GridData.CENTER, false, false); + data.horizontalSpan = 1; + button.setLayoutData(data); + button.setImage( image ); + button.setToolTipText( toolTipText); + button.addSelectionListener(listener); + return button; + } + + // ********** listener interface ********** + + /** + * Allows clients to listen for changes to the selected connection profile + * and schema. + */ + public interface Listener extends EventListener + { + void selectedConnectionProfileChanged(ConnectionProfile connectionProfile); + void selectedSchemaChanged(Schema schema); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java new file mode 100644 index 0000000000..23c60e30a8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/DefaultTableGenerationWizardPage.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.List; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.ui.wizards.NewTypeWizardPage; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.gen.internal2.ORMGenTable; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.ui.PlatformUI; + +/** + * A wizard page allowing the entry of the default table generation + * properties (Java classes package, base class, etc). + * These properties apply to all tables unless explicitly overridden (in the table generation page). + * + * @author Danny Ju + */ +public class DefaultTableGenerationWizardPage extends NewTypeWizardPage { + + private JpaProject jpaProject; + + /*the instance used to get/set the default properties.*/ + private ORMGenTable defaultsTable; + + private ORMGenCustomizer customizer; + + private TableGenPanel defaultTableGenPanel ; + + protected DefaultTableGenerationWizardPage(JpaProject jpaProject) { + super(true, "DefaultTableGenerationWizardPage"); //$NON-NLS-1$ + this.jpaProject = jpaProject; + setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_title); + setDescription( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_desc); + } + + + // -------- Initialization --------- + /** + * The wizard owning this page is responsible for calling this method with the + * current selection. The selection is used to initialize the fields of the wizard + * page. + * + * @param selection used to initialize the fields + */ + void init(IStructuredSelection selection) { + if( jpaProject != null ){ + IJavaElement jelem = this.jpaProject.getJavaProject(); + initContainerPage(jelem); + initTypePage(jelem); + } + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 4 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES); + + //Create entity access, collection type, etc + defaultTableGenPanel = new TableGenPanel(composite, 4, true , this); + + createDomainJavaClassesPropertiesGroup(composite, 4); + setControl(composite); + + + this.setPageComplete( true ); + + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + if(visible){ + ORMGenCustomizer customizer = getCustomizer(); + //If user changed the connection or schema + if( this.customizer != customizer ){ + this.customizer = customizer; + ORMGenTable newTable; + newTable = getCustomizer().createGenTable(null); + this.defaultsTable = newTable; + defaultTableGenPanel.setORMGenTable(newTable); + + //set the super class and implemented interfaces value + String baseClass = defaultsTable.getExtends()==null?"":defaultsTable.getExtends(); + setSuperClass(baseClass, true); + setSuperInterfaces(defaultsTable.getImplements(), true); + + setPackageName( defaultsTable.getPackage() ); + + + } + } + } + + private void setPackageName(String packageName) { + if( packageName==null ) + return; + // Copied from org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeWizardPage + try { + IPackageFragmentRoot srcEntryDft = null; + IJavaProject javaProject = jpaProject.getJavaProject(); + IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots(); + for (int i = 0; i < roots.length; i++) { + if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) { + srcEntryDft = roots[i]; + break; + } + } + IPackageFragmentRoot packageFragmentRoot; + if (srcEntryDft != null) + packageFragmentRoot = srcEntryDft; + else { + packageFragmentRoot = javaProject.getPackageFragmentRoot(javaProject.getResource()); + } + IFolder packageFolder = javaProject.getProject().getFolder(packageName); + IPackageFragment packageFragment = packageFragmentRoot.getPackageFragment(packageFolder.getProjectRelativePath().toOSString()); + setPackageFragment(packageFragment, true/*canBeModified*/); + } catch (CoreException e) { + JptUiPlugin.log(e); + } + } + + + protected void createDomainJavaClassesPropertiesGroup(Composite composite, int columns) { + Group parent = new Group( composite, SWT.NONE); + parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_domainJavaClass); + parent.setLayout(new GridLayout( columns, false)); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = true; + parent.setLayoutData(layoutData); + + //default Java package name only available for default table generation + createPackageControls(parent, columns); + createSuperClassControls(parent, columns); + createSuperInterfacesControls(parent, columns); + + } + + protected IStatus packageChanged() { + IStatus status = super.packageChanged(); + IPackageFragment packageFragment = getPackageFragment(); + String srcFolder = packageFragment.getPath().toPortableString(); + if(defaultsTable!=null && !status.matches(IStatus.ERROR)){ + defaultsTable.setPackage(srcFolder, packageFragment.getElementName()); + } + return status; + } + + protected IStatus superClassChanged() { + IStatus status = super.superClassChanged(); + String baseClass = getSuperClass(); + if(baseClass!=null && defaultsTable!=null && !status.matches(IStatus.ERROR)){ + String oldBaseClass = defaultsTable.getExtends(); + if( !baseClass.equals(oldBaseClass)) + defaultsTable.setExtends(baseClass); + } + return status; + } + + protected void handleFieldChanged(String fieldName) { + super.handleFieldChanged(fieldName); + if( this.fPackageStatus.matches(IStatus.ERROR) ){ + updateStatus(fPackageStatus); + }else if( this.fSuperClassStatus.matches(IStatus.ERROR)){ + updateStatus(fSuperClassStatus); + }else{ + setMessage("", IMessageProvider.NONE); + setErrorMessage(null); + updateStatus(fPackageStatus); + } + } + + @SuppressWarnings("unchecked") + protected IStatus superInterfacesChanged() { + IStatus ret = super.superInterfacesChanged(); + if( ret.isOK() ){ + List interfaces = getSuperInterfaces(); + if(defaultsTable!=null) + defaultsTable.setImplements(interfaces); + } + return ret; + } + + private ORMGenCustomizer getCustomizer(){ + GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard(); + return wizard.getCustomizer(); + } + + @Override + public final void performHelp() + { + PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID ); + } +} + diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java new file mode 100644 index 0000000000..65713b2337 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/GenerateEntitiesFromSchemaWizard.java @@ -0,0 +1,416 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.core.internal.runtime.AdapterManager; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.WorkspaceJob; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jpt.core.EntityGeneratorDatabaseAnnotationNameBuilder; +import org.eclipse.jpt.core.JpaPlatform; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.persistence.PersistenceXml; +import org.eclipse.jpt.core.internal.synch.SynchronizeClassesJob; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.BaseEntityGenCustomizer; +import org.eclipse.jpt.gen.internal2.DatabaseAnnotationNameBuilder; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.gen.internal2.PackageGenerator2; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.jpt.ui.internal.JptUiIcons; +import org.eclipse.jpt.ui.internal.JptUiMessages; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.INewWizard; +import org.eclipse.ui.IWorkbench; + +@SuppressWarnings("restriction") +public class GenerateEntitiesFromSchemaWizard extends Wizard + implements INewWizard { + + public static final String HELP_CONTEXT_ID = JptUiPlugin.PLUGIN_ID + ".GenerateEntitiesFromSchemaWizard"; //$NON-NLS-1$ + + private JpaProject jpaProject; + + private IStructuredSelection selection; + + private ORMGenCustomizer customizer = null; + + private boolean synchronizePersistenceXml; + + private PromptJPAProjectWizardPage projectPage; + + private TablesSelectorWizardPage tablesSelectorPage; + + private TableAssociationsWizardPage tableAssociationsPage; + + private DefaultTableGenerationWizardPage defaultTableGenerationPage; + + private TablesAndColumnsCustomizationWizardPage tablesAndColumnsCustomizationPage; + + public GenerateEntitiesFromSchemaWizard() { + this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities); + } + + public GenerateEntitiesFromSchemaWizard( JpaProject jpaProject, IStructuredSelection selection) { + super(); + this.jpaProject = jpaProject; + this.selection = selection; + this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities); + } + + public Image getDefaultPageImage() { + return JptUiPlugin.getImage( JptUiIcons.ENTITY_WIZ_BANNER ) ; + } + + public void addPages() { + super.addPages(); + + setForcePreviousAndNextButtons(true); + + //If this.jpaProject is not initialized because user didn't select a JPA project + if( this.jpaProject == null ){ + projectPage = new PromptJPAProjectWizardPage( HELP_CONTEXT_ID ); + this.addPage(projectPage); + return; + } + addMainPages(); + } + + private void addMainPages() + { + this.tablesSelectorPage = new TablesSelectorWizardPage( this.jpaProject ); + this.addPage(tablesSelectorPage); + + this.tableAssociationsPage = new TableAssociationsWizardPage( this.jpaProject ); + this.addPage(tableAssociationsPage); + + this.defaultTableGenerationPage = new DefaultTableGenerationWizardPage( this.jpaProject); + this.addPage(defaultTableGenerationPage); + this.defaultTableGenerationPage.init(this.selection); + + this.tablesAndColumnsCustomizationPage = new TablesAndColumnsCustomizationWizardPage( this.jpaProject ); + this.addPage(tablesAndColumnsCustomizationPage); + this.tablesAndColumnsCustomizationPage.init(selection); + } + + public ORMGenCustomizer getORMGenCustomizer(){ + return this.customizer; + } + + /** + * Create the ORMGenCustomizer when user selects a new connection profile and schema + * + * JpaPlatform implementor can provide a custom ORMGenCustomizer specific to a platform + * with AdapterFactory through Eclipse org.eclipse.core.runtime.adapters extension point: + * <pre> + * + *<extension + * point="org.eclipse.core.runtime.adapters"> + * <factory + * adaptableType="org.eclipse.jpt.eclipselink.core.internal.EclipseLinkPlatform" + * class="oracle.eclipse.tools.orm.internal.EclipseLinkORMGenCustomizerAdapterFactory"> + * <adapter + * type="oracle.eclipse.tools.orm.internal.ORMGenCustomizer"> + * </adapter> + * </factory> + *</extension> + *</pre> + * + * @param schema + */ + public ORMGenCustomizer createORMGenCustomizer(Schema schema){ + JpaPlatform jpaPlatform = this.jpaProject.getJpaPlatform(); + Object obj = AdapterManager.getDefault().getAdapter( jpaPlatform, ORMGenCustomizer.class ); + if( obj != null ){ + customizer = (ORMGenCustomizer) obj ; + customizer.init(getCustomizationFile(), schema ); + }else{ + customizer = new BaseEntityGenCustomizer( ); + customizer.init(getCustomizationFile(), schema ); + } + return customizer; + } + + protected String getCustomizationFileName() { + ConnectionProfile profile = getProjectConnectionProfile(); + String connection = profile==null?"":profile.getName(); + String name = "org.eclipse.jpt.entitygen." + (connection==null?"":connection.replace(' ', '-')); //$NON-NLS-1$ + Schema schema = getDefaultSchema(); + if ( schema!= null ) { + name += "." + schema.getName();//$NON-NLS-1$ + } + return name.toLowerCase(); + } + + /** + * Returns the nodes state file. + */ + private File getCustomizationFile() { + String projectPath = jpaProject.getProject().getLocation().toPortableString(); + File genDir = new File(projectPath + "/.settings");//$NON-NLS-1$ + genDir.mkdirs(); + return new File(genDir, getCustomizationFileName()); + } + + public boolean performFinish() { + if( this.jpaProject == null ) + return true; + + try { + this.customizer.setDatabaseAnnotationNameBuilder( buildDatabaseAnnotationNameBuilder() ); + this.customizer.save(); + } catch (IOException e) { + JptUiPlugin.log(e); + } + + this.synchronizePersistenceXml = this.tablesSelectorPage.synchronizePersistenceXml(); + + if( WarnOverwriteDialog.shouldShowDialog() ){ + if( !this.openConfirmDialog() ) + return false; + } + + WorkspaceJob genEntitiesJob = new GenerateEntitiesJob( this.jpaProject, getCustomizer() ); + + WorkspaceJob synchClassesJob = null; + if (synchronizePersistenceXml()) { + // we currently only support *one* persistence.xml file per project + PersistenceXml persistenceXml = jpaProject.getRootContextNode().getPersistenceXml(); + if (persistenceXml != null) { + // TODO casting to IFile - just trying to get rid of all compiler errors for now + synchClassesJob = new SynchronizeClassesJob((IFile) persistenceXml.getResource()); + } + } + + genEntitiesJob.schedule(); + if (synchClassesJob != null) { + synchClassesJob.schedule(); + } + + return true; + } + + // ********** generate entities job ********** + + static class GenerateEntitiesJob extends WorkspaceJob { + JpaProject jpaProject ; + ORMGenCustomizer customizer; + GenerateEntitiesJob(JpaProject jpaProject, ORMGenCustomizer customizer) { + super(JptUiMessages.EntitiesGenerator_jobName); + this.customizer = customizer; + this.jpaProject = jpaProject ; + this.setRule(jpaProject.getProject()); + } + + @Override + public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { + PackageGenerator2.generate(jpaProject.getJavaProject(),this.customizer, monitor); + return Status.OK_STATUS; + } + + } + + private DatabaseAnnotationNameBuilder buildDatabaseAnnotationNameBuilder() { + return new LocalDatabaseAnnotationNameBuilder(this.jpaProject.getJpaPlatform().getEntityGeneratorDatabaseAnnotationNameBuilder()); + } + + // ********** name builder adapter ********** + + /** + * adapt the JPA platform-supplied builder to the builder interface + * expected by the entity generator + */ + static class LocalDatabaseAnnotationNameBuilder implements DatabaseAnnotationNameBuilder { + private EntityGeneratorDatabaseAnnotationNameBuilder builder; + LocalDatabaseAnnotationNameBuilder(EntityGeneratorDatabaseAnnotationNameBuilder builder) { + super(); + this.builder = builder; + } + public String buildTableAnnotationName(String entityName, Table table) { + return this.builder.buildTableAnnotationName(entityName, table); + } + public String buildColumnAnnotationName(String attributeName, Column column) { + return this.builder.buildColumnAnnotationName(attributeName, column); + } + public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) { + return this.builder.buildJoinColumnAnnotationName(attributeName, foreignKey); + } + public String buildJoinColumnAnnotationName(Column column) { + return this.builder.buildJoinColumnAnnotationName(column); + } + public String buildJoinTableAnnotationName(Table table) { + return this.builder.buildJoinTableAnnotationName(table); + } + } + + @Override + public IWizardPage getStartingPage() { + if (this.projectPage != null) { + if (this.tablesSelectorPage != null) + return this.tablesSelectorPage; + else + return this.projectPage; + } + else + return super.getStartingPage(); + } + + public ORMGenCustomizer getCustomizer (){ + return customizer; + } + Collection<Table> getPossibleTables() { + if ( this.tablesSelectorPage != null) { + return this.tablesSelectorPage.getTables(); + } + return ( this.projectDefaultSchemaExists()) ? CollectionTools.collection( this.getDefaultSchema().tables()) : Collections.<Table>emptyList(); + } + + public ConnectionProfile getProjectConnectionProfile() { + return this.jpaProject.getConnectionProfile(); + } + + public JpaProject getJpaProject(){ + return this.jpaProject; + } + + public void setJpaProject(JpaProject jpaProject) { + if (this.jpaProject == null) { + this.jpaProject = jpaProject; + IWizardPage currentPage = getContainer().getCurrentPage(); + if (projectPage != null && currentPage.equals(projectPage)) { + addMainPages(); + } + } + } + + public Schema getDefaultSchema() { + return getJpaProject().getDefaultDbSchema() ; + } + + private boolean projectDefaultSchemaExists() { + return ( this.getDefaultSchema() != null); + } + + public boolean synchronizePersistenceXml() { + return this.synchronizePersistenceXml; + } + + public void init(IWorkbench workbench, IStructuredSelection selection) { + + Object sel = selection.getFirstElement(); + if( sel instanceof IResource ){ + IProject proj = ((IResource) sel).getProject(); + JpaProject jpaProj = JptCorePlugin.getJpaProject( proj ); + this.jpaProject = jpaProj; + }else if( sel instanceof org.eclipse.jdt.core.IPackageFragmentRoot ){ + org.eclipse.jdt.core.IPackageFragmentRoot root = (org.eclipse.jdt.core.IPackageFragmentRoot)sel; + IProject proj = root.getJavaProject().getProject(); + JpaProject jpaProj = JptCorePlugin.getJpaProject( proj ); + this.jpaProject = jpaProj; + }else if( sel instanceof org.eclipse.jdt.core.IPackageFragment){ + org.eclipse.jdt.core.IPackageFragment frag = (org.eclipse.jdt.core.IPackageFragment)sel; + IProject proj = frag.getJavaProject().getProject(); + JpaProject jpaProj = JptCorePlugin.getJpaProject( proj ); + this.jpaProject = jpaProj; + } + + this.selection = selection; + this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_generateEntities); + + } + + public boolean openConfirmDialog() { + Shell parent = Display.getDefault().getActiveShell(); + String title = JptUiEntityGenMessages.WarningDialogTitle; + String message = JptUiEntityGenMessages.GenerateEntitiesWizard_fileWillBeOverwritten; + WarnOverwriteDialog dialog = new WarnOverwriteDialog(parent, title, null, // accept + // the + // default + // window + // icon + message, MessageDialog.QUESTION, new String[] { IDialogConstants.OK_LABEL, + IDialogConstants.CANCEL_LABEL }, 0); // OK is the + // default + return dialog.open() == 0; + } + +} + +/** + * A simple dialog displaying warning message that existing files would be overwritten + */ +class WarnOverwriteDialog extends MessageDialog { + static final String DONT_SHOW_OVERWRITE_WARNING = "DONT_SHOW_OVERWRITE_WARNING"; //$NON-NLS-1$ + + public WarnOverwriteDialog (Shell parentShell, String dialogTitle, + Image dialogTitleImage, String dialogMessage, int dialogImageType, + String[] dialogButtonLabels, int defaultIndex) { + super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, + dialogButtonLabels, defaultIndex); + } + + @Override + protected Control createCustomArea(Composite composite) { + final Button checkbox = new Button( composite, SWT.CHECK ); + checkbox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_doNotShowWarning ); + checkbox.setSelection(false); + final IEclipsePreferences pref = new InstanceScope().getNode( JptUiPlugin.PLUGIN_ID); + checkbox.setLayoutData( new GridData(GridData.FILL_BOTH) ); + checkbox.addSelectionListener(new SelectionListener (){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + boolean b = checkbox.getSelection(); + if( b ){ + pref.putBoolean( DONT_SHOW_OVERWRITE_WARNING, true); + } + } + }); + return checkbox; + } + + public static boolean shouldShowDialog(){ + IEclipsePreferences pref = new InstanceScope().getNode( JptUiPlugin.PLUGIN_ID); + boolean ret = ! pref.getBoolean( DONT_SHOW_OVERWRITE_WARNING, true) ; + return( ret ); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java new file mode 100644 index 0000000000..42a346c36c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JoinColumnsPage.java @@ -0,0 +1,605 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.dialogs.IPageChangedListener; +import org.eclipse.jface.dialogs.PageChangedEvent; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ComboBoxCellEditor; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.ui.internal.util.SWTUtil; +import org.eclipse.jpt.ui.internal.util.TableLayoutComposite; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; + + +public class JoinColumnsPage extends NewAssociationWizardPage { + + private Label joinColumnsDescLabel1; + /*the table containing the association columns between table1 and table2 + * , or table1 and join table if many to many*/ + private TableViewer joinColumnsTable1; + private ArrayList<SimpleJoin> tableDataModel1 = new ArrayList<SimpleJoin>(); + private Composite tablesGroup1; + + private Label joinColumnsDescLabel2; + /*the table containing the association columns between join table and table2 + * if many to many*/ + private TableViewer joinColumnsTable2; + private ArrayList<SimpleJoin> tableDataModel2 = new ArrayList<SimpleJoin>(); + private Composite tablesGroup2; + + static final String[] JOINCOLUMNS_TABLE_COLUMN_PROPERTIES = { "referrerColumn", "referencedColumn" }; + + private static final int JOINCOLUMN1_COLUMN_INDEX = 0; + private static final int JOINCOLUMN2_COLUMN_INDEX = 1; + + protected JoinColumnsPage(ORMGenCustomizer customizer ) { + super(customizer, "JoinColumnsPage"); + setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_title); + setDescription(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_desc); + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + composite.setLayout(layout); + + tablesGroup1 = new Composite(composite, SWT.SHADOW_ETCHED_IN); + tablesGroup1.setLayoutData(new GridData()); + tablesGroup1.setLayout(new GridLayout(2, false)); + createJoinColumnsTableControl1(tablesGroup1); + + //createMtmJoinColumnsTable2(composite); + + setControl(composite); + this.setPageComplete( false); + + ((WizardDialog)getContainer()).addPageChangedListener(new IPageChangedListener(){ + public void pageChanged(PageChangedEvent event) { + if( event.getSelectedPage() == JoinColumnsPage.this ){ + ((Composite)JoinColumnsPage.this.getControl()).getParent().layout() ; + + } + } + }); + } + + private void createMtmJoinColumnsTable2(Composite composite) { + tablesGroup2 = new Composite(composite, SWT.SHADOW_ETCHED_IN); + tablesGroup2.setLayoutData(new GridData()); + tablesGroup2.setLayout(new GridLayout(2, false)); + createJoinColumnsTableControl2(tablesGroup2); + } + + /** + * Update wizard page UI with new table names + */ + public void updateWithNewTables() { + String cardinality = this.getCardinality() ; + if( Association.MANY_TO_MANY.equals( cardinality ) ){ + updateWithMtmTables(); + }else{ + updateWithOtmTables(); + } + } + + /** + * Update Wizard UI with a single TableViewer with columns from the two associated database tables + */ + public void updateWithOtmTables() { + TableColumn[] columns = joinColumnsTable1.getTable().getColumns(); + String table1Name = this.getReferrerTableName() ; + String table2Name = this.getReferencedTableName() ; + + if( table1Name ==null || table2Name == null ) + return; + + columns[0].setText( table1Name ); + columns[1].setText( table2Name ); + + //Hide the Join column table 2 + if( tablesGroup2 !=null ) + tablesGroup2.setVisible(false); + + tableDataModel1.clear(); + joinColumnsTable1.refresh(); + + String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, table2Name); + joinColumnsDescLabel1.setText(msg); + joinColumnsDescLabel1.setToolTipText( msg ); + tablesGroup1.layout(); + + String[] referrerColumnValues = getTableColumns(table1Name); + String[] referencedColumnValues = getTableColumns(table2Name); + + updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues); + + + ((Composite)this.getControl()).layout() ; + } + + /** + * Update Wizard UI with a two TableViewers with the first with columns from table1 to the MTM join table + * and the second one with columns from the MTM join table to table2 + */ + public void updateWithMtmTables() { + TableColumn[] columns = joinColumnsTable1.getTable().getColumns(); + String table1Name = this.getReferrerTableName() ; + String table2Name = this.getReferencedTableName() ; + String joinTableName = this.getJoinTableName() ; + if( table1Name==null || table2Name==null || joinTableName==null ){ + return; + } + if( tablesGroup2 == null ){ + createMtmJoinColumnsTable2( tablesGroup1.getParent()); + } + + columns[0].setText( table1Name==null?"":table1Name ); + columns[1].setText( table2Name==null?"":joinTableName ); + + //Update join column TableViewer 1 + tableDataModel1.clear(); + joinColumnsTable1.refresh(); + + String msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, table1Name, joinTableName); + joinColumnsDescLabel1.setText(msg); + joinColumnsDescLabel1.setToolTipText( msg ); + String[] referrerColumnValues = getTableColumns(table1Name); + String[] referencedColumnValues = getTableColumns(joinTableName); + + updateCellEditors(joinColumnsTable1, referrerColumnValues, referencedColumnValues ); + + //Update join column TableViewer 2 + columns = joinColumnsTable2.getTable().getColumns(); + columns[0].setText( joinTableName==null?"":joinTableName ); + columns[1].setText( table2Name==null?"":table2Name ); + tablesGroup1.layout(); + + tableDataModel2.clear(); + joinColumnsTable2.refresh(); + msg = String.format(JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label, joinTableName, table2Name); + joinColumnsDescLabel2.setText(msg); + joinColumnsDescLabel2.setToolTipText( msg ); + referrerColumnValues = getTableColumns(joinTableName); + referencedColumnValues = getTableColumns(table2Name); + updateCellEditors(joinColumnsTable2, referrerColumnValues, referencedColumnValues ); + + tablesGroup2.layout(); + + //Show the Join column TableViewer 2 + tablesGroup2.setVisible(true); + + + ((Composite)this.getControl()).layout(new Control[]{this.tablesGroup1, this.tablesGroup2}); + } + + + private void createAddRemoveButtonComposite(Composite tablesGroup, final TableViewer joinColumnsTable, final ArrayList<SimpleJoin> tableDataModel) { + //Add and Remove JoinColumns buttons + Composite buttonComposite = new Composite(tablesGroup, SWT.NULL); + GridLayout buttonLayout = new GridLayout(1, false); + buttonComposite.setLayout(buttonLayout); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.BEGINNING; + buttonComposite.setLayoutData(data); + + Button addButton = new Button(buttonComposite, SWT.PUSH); + addButton.setText( JptUiEntityGenMessages.add ); + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + addButton.setLayoutData(gridData); + addButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + @SuppressWarnings("unchecked") + public void widgetSelected(SelectionEvent e) { + + SimpleJoin join = getDefaultNewJoin(joinColumnsTable); + tableDataModel.add(join); + joinColumnsTable.refresh(); + + //Update Wizard model + TreeMap<String, String> joins = null; + if( joinColumnsTable == joinColumnsTable1 ){ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 ); + }else{ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 ); + } + joins.put( join.foreignKey, join.primaryKey); + + updatePageComplete(); + } + }); + + Button removeButton = new Button(buttonComposite, SWT.PUSH); + removeButton.setText( JptUiEntityGenMessages.remove ); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + removeButton.setLayoutData(gridData); + removeButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + @SuppressWarnings("unchecked") + public void widgetSelected(SelectionEvent e) { + StructuredSelection selection = (StructuredSelection)joinColumnsTable.getSelection(); + if( selection.isEmpty()) + return; + SimpleJoin join = (SimpleJoin)selection.getFirstElement(); + + //Update TableViewer model + tableDataModel.remove( join ); + //Update Wizard model + + TreeMap<String, String> joins = null; + if( joinColumnsTable == joinColumnsTable1 ){ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 ); + }else{ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 ); + } + joins.remove(join.foreignKey); + + joinColumnsTable.refresh(); + } + }); + + addButton.setFocus(); + + } + + protected SimpleJoin getDefaultNewJoin(TableViewer joinColumnsTable) { + String table1Name = ""; + String table2Name = ""; + if( joinColumnsTable == this.joinColumnsTable1 ){ + if( this.getJoinTableName() == null) { + table1Name = this.getReferrerTableName(); + table2Name = this.getReferencedTableName() ; + }else{ + table1Name = this.getReferrerTableName(); + table2Name = this.getJoinTableName() ; + } + }else{ + table1Name = this.getJoinTableName(); + table2Name = this.getReferencedTableName() ; + } + String[] table1ColumnValues = getTableColumns(table1Name); + String[] table2ColumnValues = getTableColumns(table2Name); + return new SimpleJoin(table1ColumnValues[0], table2ColumnValues[0]); + } + + public boolean canFlipToNextPage() { + return isPageComplete(); + } + + public void updatePageComplete() { + boolean ret = tableDataModel1.size()> 0 ; + setPageComplete( ret ); + } + + private Label createLabel(Composite container, int span, String text) { + Label label = new Label(container, SWT.NONE); + label.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + label.setLayoutData(gd); + return label; + } + + private void createJoinColumnsTableControl1(Composite tablesGroup) { + joinColumnsDescLabel1 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label ); + joinColumnsTable1 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel1); + createAddRemoveButtonComposite(tablesGroup, joinColumnsTable1, tableDataModel1); + } + + private void createJoinColumnsTableControl2(Composite tablesGroup) { + joinColumnsDescLabel2 = createLabel(tablesGroup, 2, JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_colsPage_label ); + joinColumnsTable2 = createJoinColumnsTableControl(tablesGroup, this.tableDataModel2); + createAddRemoveButtonComposite(tablesGroup, joinColumnsTable2, tableDataModel2); + } + + private TableViewer createJoinColumnsTableControl(Composite parent, ArrayList<SimpleJoin> tableDataModel ){ + + TableLayoutComposite layout= new TableLayoutComposite(parent, SWT.NONE); + addColumnLayoutData(layout); + + final org.eclipse.swt.widgets.Table table = new org.eclipse.swt.widgets.Table(layout, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER ); + table.setHeaderVisible(true); + table.setLinesVisible(true); + + TableColumn referrerColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN1_COLUMN_INDEX); + referrerColumn.setText("%table1"); + referrerColumn.setResizable(true); + + TableColumn referencedColumn = new TableColumn(table, SWT.NONE, JOINCOLUMN2_COLUMN_INDEX); + referencedColumn.setText("%table2"); + referencedColumn.setResizable(true); + + GridData gd= new GridData(GridData.FILL_BOTH); + gd.heightHint= SWTUtil.getTableHeightHint(table, 3); + gd.widthHint = 300; + layout.setLayoutData(gd); + + TableViewer newJoinColumnsTable = new TableViewer(table); + newJoinColumnsTable.setUseHashlookup(true); + newJoinColumnsTable.setLabelProvider(this.buildTableTableLabelProvider()); + newJoinColumnsTable.setContentProvider(this.buildTableTableContentProvider()); + newJoinColumnsTable.setSorter(new ViewerSorter() { + public int compare(Viewer viewer, Object e1, Object e2) { + return ((SimpleJoin) e1).foreignKey.compareTo(((SimpleJoin) e2).foreignKey); + } + }); + + newJoinColumnsTable.addPostSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + //handleTablesListSelectionChanged(event); + } + }); + populateTableDataModel(); + newJoinColumnsTable.setInput( tableDataModel ); + return newJoinColumnsTable; + } + + @SuppressWarnings("unchecked") + public void populateTableDataModel(){ + HashMap<String, Object> dataModel = (HashMap<String, Object> )getWizardDataModel(); + TreeMap<String, String> joinColumns = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1); + if( joinColumns!= null ){ + for( String referrerColumn : joinColumns.keySet() ){ + tableDataModel1.add(new SimpleJoin(referrerColumn, joinColumns.get(referrerColumn) )); + } + } + + TreeMap<String, String> joinColumns2 = (TreeMap<String, String>)dataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2); + if( joinColumns2!= null ){ + for( String referrerColumn : joinColumns2.keySet() ){ + tableDataModel2.add(new SimpleJoin(referrerColumn, joinColumns2.get(referrerColumn) )); + } + } + + } + + private IContentProvider buildTableTableContentProvider() { + return new JoinColumnsContentProvider(); + } + + + private IBaseLabelProvider buildTableTableLabelProvider() { + return new JoinColumnsTableLabelProvider(); + } + + + private void addColumnLayoutData(TableLayoutComposite layout) { + layout.addColumnData(new ColumnWeightData(50, true)); + layout.addColumnData(new ColumnWeightData(50, true)); + } + + + private void updateCellEditors(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues ){ + joinColumnsTable.setColumnProperties(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES); + ComboBoxCellEditor[] editors = new ComboBoxCellEditor[JOINCOLUMNS_TABLE_COLUMN_PROPERTIES.length]; + + editors[JOINCOLUMN1_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referrerColumnValues, SWT.SINGLE); + editors[JOINCOLUMN2_COLUMN_INDEX]= new ComboBoxCellEditor(joinColumnsTable.getTable(), referencedColumnValues, SWT.SINGLE); + + joinColumnsTable.setCellEditors(editors); + joinColumnsTable.setCellModifier(this.buildTableTableCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues )); + } + + public String[] getTableColumns(String tableName){ + Schema schema = (Schema)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_SCHEMA); + Table table = schema.getTableNamed(tableName); + Iterator<Column> columns = table.columns() ; + List<String> list = new ArrayList<String>(); + while( columns.hasNext() ){ + list.add(columns.next().getName()); + } + String[] ret = new String[list.size()]; + list.toArray(ret); + return ret; + } + + private ICellModifier buildTableTableCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) { + return new JoinColumnsCellModifier(joinColumnsTable, referrerColumnValues, referencedColumnValues); + } + + /** + * A ContentProvider translates the SimpleJoin list into a Collection for display + * + */ + private class JoinColumnsContentProvider implements IStructuredContentProvider { + + JoinColumnsContentProvider() { + super(); + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} + public void dispose() {} + public Object[] getElements(Object inputElement) { + return ((Collection<?>) inputElement).toArray(); + } + } + + /** + * Simple value object used as model backing the JFace table + * + */ + private class SimpleJoin { + public SimpleJoin(String foreignKey, String primaryKey) { + this.foreignKey = foreignKey; + this.primaryKey = primaryKey; + } + public String foreignKey; + public String primaryKey; + + public String toString(){ + return "["+ this.foreignKey + " = " + this.primaryKey + "]"; + } + } + + /** + * A CellModifier to update the join columns in the wizard data model + */ + private class JoinColumnsCellModifier implements ICellModifier { + private TableViewer joinColumnsTable; + private String[] referrerColumnValues; + private String[] referencedColumnValues; + JoinColumnsCellModifier(TableViewer joinColumnsTable, String[] referrerColumnValues, String[] referencedColumnValues) { + super(); + this.joinColumnsTable = joinColumnsTable; + this.referrerColumnValues = referrerColumnValues; + this.referencedColumnValues = referencedColumnValues; + } + + public boolean canModify(Object element, String property) { + return true; + } + + @SuppressWarnings("unchecked") + public Object getValue(Object element, String property) { +// SimpleJoin join = (SimpleJoin) element; +// if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) { +// return join.primaryKey; +// } +// return join.foreignKey; + // returnt the index of the value in the ComboxCellEditor + ArrayList<SimpleJoin> tableDataModel = (ArrayList<SimpleJoin>) joinColumnsTable.getInput(); + for(int i=0; i< tableDataModel.size(); i ++ ){ + if( tableDataModel.get(i) == element ) + return new Integer(i); + } + return new Integer(0); + + } + + /** + * element is the selected TableItem + * value is the selected item index in the comboCellEditor + */ + @SuppressWarnings("unchecked") + public void modify(Object element, String property, Object value) { + if ( ! (element instanceof TableItem)) { + return; + } + Integer index = (Integer)value; + TableItem item = (TableItem)element; + boolean unchanged = false; + SimpleJoin join = (SimpleJoin) item.getData(); + if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN1_COLUMN_INDEX])) { + unchanged = join.foreignKey.equals( referrerColumnValues[ index.intValue() ] ); + if (! unchanged) { + + //update the wizard datamodel + TreeMap<String, String> joins = null; + if( joinColumnsTable == joinColumnsTable1 ){ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 ); + }else{ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 ); + } + joins.remove(join.foreignKey); + joins.put(referrerColumnValues[ index.intValue() ], join.primaryKey); + + //Update the TableViewer model + join.foreignKey = referrerColumnValues[ index.intValue()]; + joinColumnsTable.refresh(); + } + return; + } + + if (property.equals(JOINCOLUMNS_TABLE_COLUMN_PROPERTIES[JOINCOLUMN2_COLUMN_INDEX])) { + unchanged = join.primaryKey.equals( referencedColumnValues[ index.intValue()] ) ; + if (! unchanged) { + //Update the TableViewer model + join.primaryKey = referencedColumnValues[ index.intValue()] ; + + //Update wizard data model + TreeMap<String, String> joins = null; + if( joinColumnsTable == joinColumnsTable1 ){ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1 ); + }else{ + joins = (TreeMap<String, String>)getWizardDataModel().get(NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2 ); + } + joins.put(join.foreignKey, join.primaryKey); + + joinColumnsTable.refresh(); + } + } + + + } + + } + + /** + * A table label provider to return the join column names for display + * + */ + private final class JoinColumnsTableLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + public String getColumnText(Object element, int columnIndex) { + if( !(element instanceof SimpleJoin) ) + return null; + switch (columnIndex) { + case 0: + return ((SimpleJoin)element).foreignKey; + case 1: + return ((SimpleJoin)element).primaryKey; + default: + Assert.isTrue(false); + return null; + } + } + public String getText(Object element) { + return getColumnText(element, 0); // needed to make the sorter work + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java new file mode 100644 index 0000000000..4a90b55e22 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/JptUiEntityGenMessages.java @@ -0,0 +1,112 @@ +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.osgi.util.NLS; + +/** + * Localized messages used by Dali UI. + * + * @version 2.0 + * @since 2.0 + */ +public class JptUiEntityGenMessages { + private static final String BUNDLE_NAME = "jpt_ui_entity_gen"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptUiEntityGenMessages.class; + public static String GenerateEntitiesWizard_generateEntities; + public static String GenerateEntitiesWizard_fileWillBeOverwritten; + public static String WarningDialogTitle; + public static String GenerateEntitiesWizard_doNotShowWarning; + public static String GenerateEntitiesWizard_selectJPAProject; + public static String GenerateEntitiesWizard_selectJPAProject_msg; + public static String GenerateEntitiesWizard_tableSelectPage_selectTable; + public static String GenerateEntitiesWizard_tableSelectPage_chooseEntityTable; + public static String GenerateEntitiesWizard_tableSelectPage_synchronizeClasses; + public static String GenerateEntitiesWizard_tableSelectPage_tables; + public static String GenerateEntitiesWizard_tableSelectPage_tableColumn; + //Database connection group + public static String connection; + public static String addConnectionLink; + public static String connectLink; + public static String schemaInfo; + public static String schema; + + //Default table gen properties + public static String GenerateEntitiesWizard_defaultTablePage_title; + public static String GenerateEntitiesWizard_defaultTablePage_desc; + public static String GenerateEntitiesWizard_defaultTablePage_domainJavaClass; + public static String GenerateEntitiesWizard_defaultTablePage_tableMapping; + public static String GenerateEntitiesWizard_tablePanel_className; + public static String GenerateEntitiesWizard_defaultTablePage_fetch; + public static String GenerateEntitiesWizard_defaultTablePage_collType; + public static String GenerateEntitiesWizard_defaultTablePage_sequence; + public static String GenerateEntitiesWizard_defaultTablePage_sequenceNote; + public static String GenerateEntitiesWizard_defaultTablePage_access; + public static String GenerateEntitiesWizard_defaultTablePage_keyGen; + public static String GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations; + public static String GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc; + + //Asso figure + public static String manyToOneDesc; + public static String oneToOneDesc; + public static String manyToManyDesc; + //table association wizard page + public static String GenerateEntitiesWizard_assocPage_title; + public static String GenerateEntitiesWizard_assocPage_desc; + public static String GenerateEntitiesWizard_assocPage_label; + public static String GenerateEntitiesWizard_assocPage_newAssoc; + public static String GenerateEntitiesWizard_assocPage_delAssoc; + public static String GenerateEntitiesWizard_assocEditor_genAssoc; + public static String GenerateEntitiesWizard_assocEditor_entityRef; + public static String property; + public static String cascade; + public static String GenerateEntitiesWizard_assocEditor_setRef; + public static String GenerateEntitiesWizard_assocEditor_joinedWhen; + public static String GenerateEntitiesWizard_assocEditor_tableJoin; + public static String cardinality; + public static String selectCascadeDlgTitle; + //new association wizard + public static String GenerateEntitiesWizard_newAssoc_title; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_title; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_desc; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_assocKind; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_simpleAssoc; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_m2mAssoc; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_assocTables; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_table1; + public static String GenerateEntitiesWizard_newAssoc_tablesPage_table2; + public static String GenerateEntitiesWizard_newAssoc_colsPage_title; + public static String GenerateEntitiesWizard_newAssoc_colsPage_desc; + public static String GenerateEntitiesWizard_newAssoc_colsPage_label; + public static String add; + public static String remove; + public static String GenerateEntitiesWizard_newAssoc_cardinalityPage_title; + public static String GenerateEntitiesWizard_newAssoc_cardinalityPage_desc; + public static String manyToOne; + public static String oneToMany; + public static String oneToOne; + public static String manyToMany; + //select table dialog + public static String AnnotateJavaClassWizard_classMappingPage_selectTableDlgTitle; + public static String AnnotateJavaClassWizard_classMappingPage_selectTableDlgDesc; + //individual table and column gen properties + public static String GenerateEntitiesWizard_tablesAndColumnsPage_title; + public static String GenerateEntitiesWizard_tablesAndColumnsPage_desc; + public static String GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns; + public static String GenerateEntitiesWizard_colPanel_genProp; + public static String GenerateEntitiesWizard_colPanel_colMapping; + public static String GenerateEntitiesWizard_colPanel_propName; + public static String GenerateEntitiesWizard_colPanel_propType; + public static String GenerateEntitiesWizard_colPanel_mapKind; + public static String GenerateEntitiesWizard_colPanel_colUpdateable; + public static String GenerateEntitiesWizard_colPanel_colInsertable; + public static String GenerateEntitiesWizard_colPanel_beanProp; + public static String GenerateEntitiesWizard_colPanel_getterScope; + public static String GenerateEntitiesWizard_colPanel_setterScope; + static { + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); + } + + private JptUiEntityGenMessages() { + throw new UnsupportedOperationException(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java new file mode 100644 index 0000000000..ef6e3b5649 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizard.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.TreeMap; + +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; + + +public class NewAssociationWizard extends Wizard { + + public static String ASSOCIATION_SCHEMA = "ASSOCIATION_SCHEMA"; + public static String ASSOCIATION_REFERRER_TABLE = "ASSOCIATION_REFERRER_TABLE"; + public static String ASSOCIATION_REFERENCED_TABLE = "ASSOCIATION_REFERENCED_TABLE"; + public static String ASSOCIATION_JOIN_COLUMNS1 = "ASSOCIATION_REFERRER_COLUMNS1"; + public static String ASSOCIATION_JOIN_COLUMNS2 = "ASSOCIATION_REFERRER_COLUMNS2"; //used in MTM associations only + public static String ASSOCIATION_JOIN_TABLE = "ASSOCIATION_JOIN_TABLE"; // TreeMap<String, String> + public static String ASSOCIATION_CADINALITY = "ASSOCIATION_CADINALITY"; + + private JpaProject jpaProject; + private HashMap<String, Object> associationDataModel = new HashMap<String, Object>(); + + private ORMGenCustomizer customizer = null; + + private AssociationTablesPage associationTablesPage; + private JoinColumnsPage joinColumnsPage; + private CardinalityPage cardinalityPage; + + public NewAssociationWizard( JpaProject jpaProject, ORMGenCustomizer customizer ) { + super(); + this.jpaProject = jpaProject; + this.customizer = customizer; + this.setWindowTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_newAssoc_title); + + this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_SCHEMA, this.customizer.getSchema()); + this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1, new TreeMap<String, String>()); + this.associationDataModel.put( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2, new TreeMap<String, String>()); + } + + public void addPages() { + super.addPages(); + this.associationTablesPage = new AssociationTablesPage( customizer ); + addPage(this.associationTablesPage); + + this.joinColumnsPage = new JoinColumnsPage(customizer); + addPage(this.joinColumnsPage); + + this.cardinalityPage = new CardinalityPage(customizer); + addPage(this.cardinalityPage); + } + + public boolean performFinish() { + return true; + } + + public ORMGenCustomizer getCustomizer (){ + return customizer; + } + + public JpaProject getJpaProject(){ + return this.jpaProject; + } + +// public Schema getDefaultSchema() { +// return getJpaProject().getDefaultDbSchema(); +// } +// +// private boolean projectDefaultSchemaExists() { +// return ( this.getDefaultSchema() != null); +// } + + public HashMap<String, Object> getDataModel(){ + return this.associationDataModel; + } + + public void updateTableNames(){ + IWizardPage[] pages = this.getPages(); + for( IWizardPage page : pages){ + ((NewAssociationWizardPage)page).updateWithNewTables(); + } + } + + @SuppressWarnings("unchecked") + public Association getNewAssociation(){ + String referrerTableName =getReferrerTableName(); + String referencedTableName = getReferencedTableName(); + List<String> referrerColNames = new ArrayList<String>(); + List<String> referencedColNames = new ArrayList<String>(); + + String cardinality = (String)associationDataModel.get( NewAssociationWizard.ASSOCIATION_CADINALITY ); + if( cardinality.equals(Association.MANY_TO_MANY) ){ + return createManyToManyAssociation(); + } + + Object value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1); + if(value!=null){ + TreeMap<String, String> joinColumns = (TreeMap<String, String>)value; + for( String pk : joinColumns.keySet()){ + referrerColNames.add(pk); + referencedColNames.add( joinColumns.get(pk)); + } + } + + /*if one-to-many then convert it to many-to-one to be consistent + * with the associations computed from the db foreign keys. + * Don't see at this point how one-to-many would + * affect the generation.*/ + if( cardinality.equals(Association.ONE_TO_MANY) ){ + cardinality = Association.MANY_TO_ONE; + + String temp1 = referrerTableName; + referrerTableName = referencedTableName; + referencedTableName = temp1; + + List<String> temp2 = referrerColNames; + referrerColNames = referencedColNames; + referencedColNames = temp2; + } + + Association association = null; + association = new Association(this.customizer, referrerTableName, referrerColNames , referencedTableName, referencedColNames); + association.setCardinality( cardinality ); + association.setCustom(true); + return association; + } + + @SuppressWarnings("unchecked") + private Association createManyToManyAssociation() { + String referrerTableName =getReferrerTableName(); + String joinTable = getJoinTableName(); + String referencedTableName = getReferencedTableName(); + + List<String> referrerColNames = new ArrayList<String>(); + List<String> referrerJoinColNames = new ArrayList<String>(); + Object value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS1); + if(value!=null){ + TreeMap<String, String> joinColumns = (TreeMap<String, String>)value; + for( String pk : joinColumns.keySet()){ + referrerColNames.add(pk); + referrerJoinColNames.add( joinColumns.get(pk)); + } + } + + value = associationDataModel.get( NewAssociationWizard.ASSOCIATION_JOIN_COLUMNS2); + List<String> referencedColNames = new ArrayList<String>(); + List<String> referencedJoinColNames = new ArrayList<String>(); + if(value!=null){ + TreeMap<String, String> joinColumns = (TreeMap<String, String>)value; + for( String pk : joinColumns.keySet()){ + referencedJoinColNames.add(pk); + referencedColNames.add( joinColumns.get(pk)); + } + } + + + Association association = null; + association = new Association(this.customizer, referrerTableName, referrerColNames, + referencedTableName, referencedColNames, joinTable, referrerJoinColNames, referencedJoinColNames); + return association; + } + + String getReferrerTableName(){ + return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_REFERRER_TABLE); + } + + String getReferencedTableName(){ + return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_REFERENCED_TABLE); + } + + String getJoinTableName(){ + return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_JOIN_TABLE ); + } + + String getCardinality(){ + return (String)associationDataModel.get(NewAssociationWizard.ASSOCIATION_CADINALITY ); + } + +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java new file mode 100644 index 0000000000..6eaf73e9cb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/NewAssociationWizardPage.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.HashMap; + +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; + + +public abstract class NewAssociationWizardPage extends WizardPage { + + protected ORMGenCustomizer customizer; + + public NewAssociationWizardPage(ORMGenCustomizer customizer, String name) { + super(name); + this.customizer = customizer ; + } + + protected HashMap<String, Object> getWizardDataModel(){ + return ((NewAssociationWizard)this.getWizard()).getDataModel(); + } + + protected String getReferrerTableName(){ + return ((NewAssociationWizard)getWizard()).getReferrerTableName(); + } + + protected String getReferencedTableName(){ + return ((NewAssociationWizard)getWizard()).getReferencedTableName(); + } + + protected String getJoinTableName(){ + return ((NewAssociationWizard)getWizard()).getJoinTableName(); + } + + protected String getCardinality(){ + return ((NewAssociationWizard)getWizard()).getCardinality() ; + } + + public void updateWithNewTables() { + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java new file mode 100644 index 0000000000..5189394c3c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/PromptJPAProjectWizardPage.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.PlatformUI; + +public class PromptJPAProjectWizardPage extends WizardPage { + + private static String SELECT_PROJECT_PAGE_NAME = "SelectJPAProject"; //$NON-NLS-1$ + private Table projTable; + private TableViewer projTableViewer; + private static int PROJECT_NAME_COLUMN_INDEX = 0; + private final String helpContextId; + + protected PromptJPAProjectWizardPage( final String helpContextId ) { + super(SELECT_PROJECT_PAGE_NAME); + setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject ); + setMessage( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject_msg ); + this.helpContextId = helpContextId; + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 1; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + Label label = new Label( composite, SWT.NONE ); + label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_selectJPAProject ); + + projTableViewer = new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL | SWT.VIRTUAL); + projTable = projTableViewer.getTable(); + GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true ); + projTable.setLayoutData(gd); + + projTable.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + handleJpaProjectSelection(); + } + + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + + }); + + projTableViewer = new TableViewer(projTable); + projTableViewer.setLabelProvider(new ProjectTableLabelProvider()); + projTableViewer.setContentProvider(new ProjectTableContentProvider()); + fillJpaProjectList(); + setControl( composite ); + validate(); + } + + private void handleJpaProjectSelection() { + if (projTable.getSelectionIndex() != -1) { + TableItem item = projTable.getItem(projTable.getSelectionIndex()); + String projName = item.getText(0); + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projName); + JpaProject jpaProj = JptCorePlugin.getJpaProject( project ); + ((GenerateEntitiesFromSchemaWizard)getWizard()).setJpaProject(jpaProj); + validate(); + } + } + + private void fillJpaProjectList() { + IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + List<String> projNames = new ArrayList<String>(); + for ( IProject project : projects ) + { + JpaProject jpaProj = JptCorePlugin.getJpaProject( project ); + if ( jpaProj != null ) { + projNames.add(project.getName()); + } + } + projTableViewer.setInput(projNames); + } + + private void validate() { + if (projTable.getSelectionIndex() != -1) + setPageComplete(true); + else + setPageComplete(false); + } + + @Override + public final void performHelp() + { + PlatformUI.getWorkbench().getHelpSystem().displayHelp( this.helpContextId ); + } + + // inner classes + private final class ProjectTableLabelProvider extends LabelProvider implements ITableLabelProvider { + public Image getColumnImage(Object element, int columnIndex) + { + if (columnIndex == PROJECT_NAME_COLUMN_INDEX) + return PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ide.IDE.SharedImages.IMG_OBJ_PROJECT); + return null; + } + + public String getColumnText(Object element, int columnIndex) + { + assert element instanceof String; + String projectName = (String)element; + if (columnIndex == PROJECT_NAME_COLUMN_INDEX) + return projectName; + return null; + } + } + + private final class ProjectTableContentProvider implements IStructuredContentProvider + { + public Object[] getElements(Object inputElement){ + return ((Collection<?>) inputElement).toArray(); + } + + public void dispose(){} + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput){} + + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java new file mode 100644 index 0000000000..98b6b61d3e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SWTUtil.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Collection of utility methods to create SWT UI + * + */ +public class SWTUtil { + /** + * Set the layoutData of the input control to occupy specified number of columns + * @param c + * @param columns + */ + public static void fillColumns(Control c, int columns){ + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + c.setLayoutData(layoutData); + return ; + } + + public static void fillColumnsWithIndent(Control c, int columns, int indent){ + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + layoutData.horizontalIndent = indent ; + c.setLayoutData(layoutData); + return ; + } + + public static Label createLabel(Composite container, int span, String text) { + Label label = new Label(container, SWT.NONE); + label.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + label.setLayoutData(gd); + return label; + } + + /** + * Create a new label which occupies one grid column + * @param parent + * @param text + */ + public static Label newLabel(Composite parent, String text) { + Label label = new Label( parent, SWT.NONE); + label.setText( text ); + label.setLayoutData(new GridData()); + return label; + } + + /** + * Create a new label which occupies one grid column + * @param parent + * @param text + */ + public static Label newLabelWithIndent(Composite parent, String text, int indent) { + Label label = new Label( parent, SWT.NONE); + label.setText( text ); + GridData layoutData = new GridData(); + layoutData.horizontalAlignment = SWT.BEGINNING; + layoutData.verticalAlignment = SWT.TOP ; + layoutData.horizontalIndent = indent ; + label.setLayoutData(layoutData); + return label; + } + + /** + * Creates a separator line. Expects a <code>GridLayout</code> with at least 1 column. + * + * @param composite the parent composite + * @param nColumns number of columns to span + */ + @SuppressWarnings("restriction") + public static void createSeparator(Composite composite, int nColumns) { + (new org.eclipse.jdt.internal.ui.wizards.dialogfields.Separator( + SWT.SEPARATOR | SWT.HORIZONTAL)).doFillIntoGrid(composite, nColumns, 5); + } + + + public static Button createButton(Composite container, int span, String text, int style) { + Button btn = new Button(container, style); + btn.setText(text); + GridData gd = new GridData(); + gd.horizontalSpan = span; + btn.setLayoutData(gd); + return btn; + } + + public static Combo createCombo(Composite container, int span ) { + Combo combo = new Combo(container, SWT.SINGLE | SWT.READ_ONLY); + GridData gd = new GridData(); + gd.horizontalSpan = span; + gd.grabExcessHorizontalSpace=true; + gd.horizontalAlignment = SWT.FILL; + combo.setLayoutData(gd); + return combo; + } + + public static Text createText(Composite container, int span ) { + Text text = new Text(container, SWT.BORDER); + GridData gd = new GridData(); + gd.horizontalSpan = span; + gd.grabExcessHorizontalSpace=true; + gd.horizontalAlignment = SWT.FILL; + text.setLayoutData(gd); + return text; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java new file mode 100644 index 0000000000..66311e56f4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/SelectTableDialog.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; + +/** + * A database table selection dialog which allows user to filter tables by name + */ +public class SelectTableDialog extends ElementListSelectionDialog { + + public SelectTableDialog(Shell shell){ + super(shell, new ILabelProvider(){ + public Image getImage(Object element) { + return CommonImages.createImage(CommonImages.TABLE_IMAGE) ; + } + + public String getText(Object element) { + return element.toString(); + } + public void addListener(ILabelProviderListener listener) {} + public void dispose() {} + + public boolean isLabelProperty(Object element, String property) { + return false; + } + + public void removeListener(ILabelProviderListener listener) {} + + }); + this.setTitle( JptUiEntityGenMessages.AnnotateJavaClassWizard_classMappingPage_selectTableDlgTitle );// + this.setMessage( JptUiEntityGenMessages.AnnotateJavaClassWizard_classMappingPage_selectTableDlgDesc);// + } + + public SelectTableDialog(Shell shell, Schema schema){ + this(shell); + + ArrayList<String> list = new ArrayList<String>(); + Iterator<Table> tablesIt = schema.tables(); + while (tablesIt.hasNext()) + { + Table table = tablesIt.next(); + list.add(table.getName()); + } + this.setElements( list.toArray() ); + + } + + public SelectTableDialog(Shell shell, List<String> tableNames){ + this(shell); + this.setElements( tableNames.toArray() ); + } + public String getSelectedTable() + { + String tableName = (String)this.getFirstResult(); + return tableName ; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java new file mode 100644 index 0000000000..b36e5f6109 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableAssociationsWizardPage.java @@ -0,0 +1,751 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + + +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.fillColumns; +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.newLabel; +import static org.eclipse.jpt.ui.internal.wizards.gen.SWTUtil.newLabelWithIndent; + +import java.util.List; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.core.JavaConventions; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.ui.dialogs.StatusUtil; +import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; +import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; +import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; +import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField; +import org.eclipse.jface.window.Window; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.AssociationRole; +import org.eclipse.jpt.gen.internal2.ORMGenColumn; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; + +public class TableAssociationsWizardPage extends WizardPage { + + private JpaProject jpaProject; + private ORMGenCustomizer customizer ; + + private AssociationsListComposite associationList; + private Association selectedAssociation; + private Button deleteAssociationLink ; + private Button createAssociationLink ; + + //Controls in Association Edit Panel + private Composite associationsEditPanel ; + private Button generateAssociationCheckBox; + private Label cardinalityLabel ; + private Combo cardinalityCombo ; + /*whether to generate the referrer-->referenced role.*/ + private Button referrerRoleCheckBox; + /*the name of the property in the referrer-->referenced role.*/ + private Label referrerRolePropertyLabel; + private Text referrerRolePropertyField ; + /*the cascade in the referrer-->referenced role.*/ + @SuppressWarnings("restriction") + private StringButtonDialogField referrerRoleCascadeField; + /*whether to generate the referenced->referrer role.*/ + private Button referencedRoleCheckBox; + /*the name of the property in the referenced->referrer role.*/ + private Label referencedRolePropertyLabel; + private Text referencedRolePropertyField ; + /*the cascade in the referenced->referrer role.*/ + @SuppressWarnings("restriction") + private StringButtonDialogField referencedRoleCascadeField; + private Label joinConditionLabel; + private Text joinConditionText; + + private Composite detailPanel ; + private StackLayout detailPanelStatckLayout ; + private Composite emptyPanel ; + + protected TableAssociationsWizardPage(JpaProject jpaProject ) { + super("Table Associations"); //$NON-NLS-1$ + this.jpaProject = jpaProject; + setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_title); + setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_desc); + + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 2 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES); + + Label label = new Label(composite, SWT.NONE); + label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_label ); + GridData gd = new GridData(); + gd.horizontalSpan = 2; + label.setLayoutData( gd ); + + createAssociationsListPanel(composite); + createAddDeleteButtons(composite, nColumns); + SWTUtil.createSeparator(composite, nColumns); + + createDetailPanel(composite); + setControl(composite); + + composite.layout(true); + this.setPageComplete( true); + + } + + private void createAddDeleteButtons(Composite composite, int columns) { + + Composite c = new Composite( composite, SWT.NONE); + fillColumns(c, 1); + c.setLayout( new GridLayout(1,true) ); + + createAssociationLink = new Button(c, SWT.NONE); + createAssociationLink.setToolTipText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_newAssoc ); + createAssociationLink.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_ADD) ); + createAssociationLink.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + launchNewAssociationsWizard(); + } + + }); + + deleteAssociationLink = new Button(c, SWT.NONE); + deleteAssociationLink.setForeground( new Color(Display.getDefault(), 0,0,255)); + deleteAssociationLink.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_DELETE) ); + deleteAssociationLink.setToolTipText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_delAssoc ); + deleteAssociationLink.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + Association association = associationList.getSelectedAssociation(); + if( association != null ){ + ORMGenCustomizer customizer = getCustomizer(); + customizer.deleteAssociation(association); + List<Association> associations = customizer.getAssociations(); + associationList.updateAssociations(associations); + if( associations.size()==0 ){ + hideAssociationDetail(); + } + } + } + }); + deleteAssociationLink.setEnabled(false); + + } + + private void createGenerateAssociationCheckbox(Composite composite, int columns) { + generateAssociationCheckBox = new Button(composite, SWT.CHECK); + generateAssociationCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_genAssoc); + generateAssociationCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + Association association = associationList.getSelectedAssociation(); + if( association == null ) + return; + association.setGenerated(generateAssociationCheckBox.getSelection()); + + updateAssociationEditPanel(association); + associationList.updateSelectedAssociation(); + } + + }); + + fillColumns(generateAssociationCheckBox, columns-1); + newLabel(composite, ""); + } + + @SuppressWarnings("restriction") + private void createGenerateReferrerRoleControls(Composite parent, int columns) { + referrerRoleCheckBox = new Button(parent, SWT.CHECK); + referrerRoleCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef ); + referrerRoleCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + boolean generate = referrerRoleCheckBox.getSelection(); + //referrerRolePropertyField.setEditable( generate ); + referrerRolePropertyLabel.setEnabled( generate ); + referrerRolePropertyField.setEnabled( generate ); + referrerRoleCascadeField.setEnabled(generate); + + //If both referencedRoleCheckBox and referencedRoleCheckBox unchecked, + //the association itself shouldn't be generated + if( !generate && !referencedRoleCheckBox.getSelection()){ + generateAssociationCheckBox.setSelection(false); + cardinalityLabel.setEnabled( false ); + cardinalityCombo.setEnabled(false); + referrerRoleCheckBox.setEnabled(false); + referencedRoleCheckBox.setEnabled(false); + } + + directionalityCheckBoxChanged( ); + + if( generate ){ + AssociationRole role = selectedAssociation.getReferrerRole(); + referrerRolePropertyField.setText( role.getPropertyName() ); + } + } + + }); + + SWTUtil.fillColumnsWithIndent(referrerRoleCheckBox , columns-1, 20 ); + newLabel(parent, "");//$NON-NLS-1$ + + referrerRolePropertyLabel = newLabelWithIndent( parent, JptUiEntityGenMessages.property, 40 ); //$NON-NLS-1$ + referrerRolePropertyField = new Text( parent, SWT.BORDER); + fillColumns(referrerRolePropertyField, 2); + referrerRolePropertyField.addModifyListener(new ModifyListener(){ + @SuppressWarnings("deprecation") + public void modifyText(ModifyEvent e) { + if( selectedAssociation.getReferrerRole() == null ) + return; + String fieldName = referrerRolePropertyField.getText(); + IStatus status = JavaConventions.validateFieldName( fieldName ); + if( !status.matches(IStatus.ERROR) ){ + selectedAssociation.getReferrerRole().setPropertyName(fieldName); + } + updateStatus(status); + } + }); + + Label label = new Label( parent, SWT.NONE); + label.setText( "" );//$NON-NLS-1$ + label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); + + referrerRoleCascadeField = new StringButtonDialogField( new IStringButtonAdapter(){ + public void changeControlPressed(DialogField field) { + if( editCascade( selectedAssociation.getReferrerRole() )){ + referrerRoleCascadeField.setText(selectedAssociation.getReferrerRole().getCascade()); + } + } + }) ; + referrerRoleCascadeField.setLabelText( JptUiEntityGenMessages.cascade ); //$NON-NLS-1$ + referrerRoleCascadeField.setButtonLabel(""); //$NON-NLS-1$ + referrerRoleCascadeField.doFillIntoGrid(parent, 3); + referrerRoleCascadeField.getTextControl(parent).setEditable(false); + int maxFieldWidth = convertWidthInCharsToPixels(40); + LayoutUtil.setWidthHint(referrerRoleCascadeField.getTextControl(null), maxFieldWidth ); + Button btn = referrerRoleCascadeField.getChangeControl(null); + GridData data = (GridData)btn.getLayoutData(); + btn.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE) ); + data.horizontalAlignment = SWT.BEGINNING; + data.widthHint = 30; + btn.setLayoutData(data); + + Label labelCtrl = referrerRoleCascadeField.getLabelControl(parent); + data = (GridData)labelCtrl.getLayoutData(); + data.horizontalIndent = 40 ; + labelCtrl.setLayoutData(data); + + + label = new Label( parent, SWT.NONE); + label.setText( "" );//$NON-NLS-1$ + label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); + + } + + + public void setVisible(boolean visible) { + super.setVisible(visible); + if( visible ){ + hideAssociationDetail(); + updateAssociationsListPanel(); + } + } + + private void hideAssociationDetail( ){ + this.detailPanelStatckLayout.topControl = emptyPanel; + this.detailPanel.layout(); + this.detailPanel.getParent().layout(); + } + + /** + * Updates the status line and the OK button according to the given status + * + * @param status status to apply + */ + @SuppressWarnings("restriction") + protected void updateStatus(IStatus status) { + setPageComplete(!status.matches(IStatus.ERROR)); + + StatusUtil.applyToStatusLine(this, status); + if( status.getCode() == Status.OK ){ + setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_assocPage_desc); + } + } + + @SuppressWarnings("restriction") + private void createGenerateReferencedRoleControls(Composite parent, int columns) { + referencedRoleCheckBox = new Button(parent, SWT.CHECK); + referencedRoleCheckBox.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef ); + referencedRoleCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + boolean generate = referencedRoleCheckBox.getSelection(); + referencedRolePropertyLabel.setEnabled( generate); + referencedRolePropertyField.setEnabled( generate); + referencedRoleCascadeField.setEnabled(generate); + + if( !generate && !referrerRoleCheckBox.getSelection()){ + generateAssociationCheckBox.setSelection(false); + cardinalityCombo.setEnabled(false); + referrerRoleCheckBox.setEnabled(false); + referencedRoleCheckBox.setEnabled(false); + } + directionalityCheckBoxChanged(); + if( generate ){ + AssociationRole role = selectedAssociation.getReferencedRole(); + referencedRolePropertyField.setText( role.getPropertyName() ); + } + } + + }); + + SWTUtil.fillColumnsWithIndent( referencedRoleCheckBox , columns-1, 20 ); + newLabel(parent, "");//$NON-NLS-1$ + + referencedRolePropertyLabel = SWTUtil.newLabelWithIndent(parent, JptUiEntityGenMessages.property, 40 ); //$NON-NLS-1$ + + referencedRolePropertyField = new Text( parent, SWT.BORDER); + fillColumns(referencedRolePropertyField, 2); + referencedRolePropertyField.addModifyListener(new ModifyListener(){ + public void modifyText(ModifyEvent e) { + if( selectedAssociation.getReferencedRole() == null ) + return ; + + String fieldName = referencedRolePropertyField.getText(); + IStatus status = JavaConventions.validateIdentifier(fieldName, + CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3); + if( !status.matches(IStatus.ERROR) ){ + if( !fieldName.equals(selectedAssociation.getReferencedRole().getPropertyName()) ) + selectedAssociation.getReferencedRole().setPropertyName(fieldName); + } + updateStatus(status); + } + }); + + + Label label = new Label( parent, SWT.NONE); + label.setText( "" );//$NON-NLS-1$ + label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); + + + referencedRoleCascadeField = new StringButtonDialogField( new IStringButtonAdapter(){ + public void changeControlPressed(DialogField field) { + if( editCascade( selectedAssociation.getReferencedRole() ) ){ + referencedRoleCascadeField.setText( selectedAssociation.getReferencedRole().getCascade() ); + } + } + }) ; + referencedRoleCascadeField.setLabelText( JptUiEntityGenMessages.cascade ); //$NON-NLS-1$ + referencedRoleCascadeField.setButtonLabel(""); //$NON-NLS-1$ + referencedRoleCascadeField.doFillIntoGrid(parent, 3); + referencedRoleCascadeField.getTextControl(parent).setEditable( false); + int maxFieldWidth = convertWidthInCharsToPixels(40); + LayoutUtil.setWidthHint(referencedRoleCascadeField.getTextControl(null), maxFieldWidth ); + Button btn = referencedRoleCascadeField.getChangeControl(null); + btn.setImage( CommonImages.createImage( CommonImages.DESC_BUTTON_BROWSE) ); + GridData data = (GridData)btn.getLayoutData(); + data.horizontalAlignment = SWT.BEGINNING; + data.widthHint = 30; + btn.setLayoutData(data); + + Label labelCtrl = referencedRoleCascadeField.getLabelControl(parent); + data = (GridData)labelCtrl.getLayoutData(); + data.horizontalIndent = 40 ; + labelCtrl.setLayoutData(data); + + label = new Label( parent, SWT.NONE); + label.setText( "" );//$NON-NLS-1$ + label.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL)); + + } + + private void createDetailPanel(Composite composite ) { + + this.detailPanel = new Composite( composite, SWT.NONE); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.grabExcessVerticalSpace = false; + this.detailPanel.setLayoutData(gd); + this.detailPanelStatckLayout = new StackLayout(); + this.detailPanel.setLayout( this.detailPanelStatckLayout ); + + emptyPanel = new Composite( detailPanel, SWT.NONE); + emptyPanel.setLayoutData(new GridData()); + detailPanelStatckLayout.topControl = emptyPanel; + detailPanel.layout(); + + composite.layout(); + } + + + private Composite createAssociationsEditPanel(Composite composite, int columns) { + Composite parent = new Composite( composite, SWT.NONE); + fillColumns(parent, 4); + + createGenerateAssociationCheckbox(parent,columns); + int nColumns= 4 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + parent.setLayout(layout); + + //Cardinality + cardinalityLabel = new Label(parent, SWT.NONE); + cardinalityLabel.setText( JptUiEntityGenMessages.cardinality); + GridData gd = new GridData(); + gd.horizontalIndent = 20; + cardinalityLabel.setLayoutData( gd ); + + cardinalityCombo = new Combo(parent, SWT.SINGLE | SWT.READ_ONLY ); + + fillColumns(cardinalityCombo, 1); + + cardinalityCombo.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + selectedAssociation.setCardinality( cardinalityCombo.getText()); + associationList.updateSelectedAssociation(); + } + }); + + //Adding a filler column + Label label = new Label( parent, SWT.NONE); + label.setText( "");//$NON-NLS-1$ + GridData layoutData = new GridData(); + layoutData.horizontalSpan = 2; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + label.setLayoutData(layoutData); + + //Table join condition + joinConditionLabel = newLabelWithIndent(parent, JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_tableJoin, 20 ); + + joinConditionText = new Text( parent, SWT.MULTI | SWT.BORDER ); + joinConditionText.setEditable(false); + joinConditionText.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen); + layoutData = new GridData(); + layoutData.horizontalSpan = 2; + layoutData.verticalAlignment = SWT.TOP; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + layoutData.heightHint = 50; + joinConditionText.setLayoutData(layoutData); + newLabel(parent, "");//$NON-NLS-1$ + + //Generate UI controls for ReferrerRole + createGenerateReferrerRoleControls(parent, columns); + + //Generate UI controls for ReferencedRole + createGenerateReferencedRoleControls(parent, columns); + + + return parent; + } + + public boolean editCascade(AssociationRole role) { + CascadeDialog dlg = CascadeDialog.create(role); + if (dlg.open() == Window.CANCEL ) { + return false; + } + + return true; + } + + private void createAssociationsListPanel(Composite parent) { + Composite composite = new Composite( parent, SWT.NULL ); + composite.setLayout( new FillLayout()); + composite.setBackground(new Color(Display.getDefault(),255, 0,0) ); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = 1; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = false; + layoutData.grabExcessVerticalSpace = true; + layoutData.widthHint = 400; + layoutData.heightHint = 400; + composite.setLayoutData(layoutData); + + associationList = new AssociationsListComposite(composite, this); + } + + private void launchNewAssociationsWizard() { + ORMGenCustomizer customizer = getCustomizer(); + NewAssociationWizard wizard = new NewAssociationWizard(this.jpaProject, customizer ); + + WizardDialog dialog = new WizardDialog( this.getShell(), wizard); + dialog.create(); + int returnCode = dialog.open(); + if (returnCode == Window.OK) { + Association association = wizard.getNewAssociation(); + if( association !=null ){ + customizer.addAssociation(association); + updateForeignKeyColumnGenProperty(association); + updateAssociationsListPanel(); + } + } + } + /** + * For user created association: + * If association is to be generated, no need to generate the getter/setter for the column itself + */ + private void updateForeignKeyColumnGenProperty(Association association) { + //Need to process MANY_TO_ONE only since the the associations list are optimized to have MANY_TO_ONE + if( association.isCustom() && association.getCardinality().equals( Association.MANY_TO_ONE ) ){ + boolean generateColumn = !association.isGenerated(); + //The "MANY" side DB table + //ORMGenTable table1 = association.getReferrerTable(); + //The "ONE" side DB table + //ORMGenTable table2 = association.getReferencedTable(); + //The list of foreign key columns in the MANY side, should not be generated + //The list of primary keys in the ONE side, will be generated + //List<ORMGenColumn> list2 = association.getReferencedColumns(); + List<ORMGenColumn> list1 = association.getReferrerColumns(); + for(ORMGenColumn c : list1 ){ + if( c.isGenerated() != generateColumn){ + if( !generateColumn && DTPUtil.isPrimaryKey( c.getDbColumn() ) ){ + continue; + } + c.setGenerated(generateColumn); + c.setInsertable(generateColumn); + c.setUpdateable(generateColumn); + } + } + } + } + + private void updateAssociationsListPanel() { + ORMGenCustomizer customizer = getCustomizer(); + //If user changed the connection or schema + if( this.customizer != customizer ){ + this.customizer = customizer; + } + List<Association> associations = customizer.getAssociations(); + this.associationList.updateAssociations( associations ); + } + + @SuppressWarnings("restriction") + public void updateAssociationEditPanel(Association association) { + this.selectedAssociation = association; + + boolean enabled = association.isCustom(); + this.deleteAssociationLink.setEnabled(enabled); + + //Create and display the associationsEditPanel if it was hidden before + if( associationsEditPanel == null ){ + associationsEditPanel = this.createAssociationsEditPanel(this.detailPanel, 4); + } + this.detailPanelStatckLayout.topControl = associationsEditPanel; + this.detailPanel.layout(); + this.detailPanel.getParent().layout(); + + //Update the UI controls from the model + String table1Name = association.getReferrerTableName(); + String table2Name = association.getReferencedTableName(); + String joinTableName = association.getJoinTableName(); + + boolean isGenerated = association.isGenerated(); + this.generateAssociationCheckBox.setSelection(isGenerated); + this.referrerRolePropertyLabel.setEnabled( isGenerated ); + this.referrerRolePropertyField.setEnabled( isGenerated ); + this.referrerRoleCheckBox.setEnabled( isGenerated ); + this.referencedRolePropertyLabel.setEnabled( isGenerated ); + this.referencedRolePropertyField.setEnabled( isGenerated ); + this.referencedRoleCheckBox.setEnabled( isGenerated ); + this.cardinalityLabel.setEnabled(isGenerated); + this.cardinalityCombo.setEnabled(isGenerated); + this.joinConditionLabel.setEnabled( isGenerated ); + this.joinConditionText.setEnabled( isGenerated ); + + String cardinality = association.getCardinality(); + if( Association.MANY_TO_MANY.equals( cardinality ) ){ + cardinalityCombo.removeAll(); + cardinalityCombo.add( Association.MANY_TO_MANY); + }else{ + cardinalityCombo.removeAll(); + cardinalityCombo.add( Association.MANY_TO_ONE); + cardinalityCombo.add( Association.ONE_TO_ONE); + } + + cardinalityCombo.setText(cardinality); + cardinalityCombo.setEnabled(enabled); + + String text = null; + //if MTM + if( Association.MANY_TO_MANY.equals( cardinality ) ){ + text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef, table2Name, table1Name); + }else{ + text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef, table2Name, table1Name); + } + this.referrerRoleCheckBox.setText(text); + + //if OTO + if( Association.ONE_TO_ONE.equals( cardinality ) ){ + text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_entityRef, table1Name, table2Name); + }else{ + text = String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_setRef, table1Name, table2Name); + } + this.referencedRoleCheckBox.setText(text); + + //AssociationRole properties + AssociationRole referrerRole = association.getReferrerRole(); + if( referrerRole != null){ + this.referrerRoleCheckBox.setSelection( true ); + this.referrerRolePropertyField.setEditable(true); + this.referrerRolePropertyField.setText(referrerRole.getPropertyName()); + this.referrerRoleCascadeField.setEnabled(true); + String cascade = referrerRole.getCascade(); + if( cascade!=null ) + this.referrerRoleCascadeField.setText( cascade ); + + //if MTO: + if( Association.MANY_TO_ONE.equals( cardinality ) ){ + this.referrerRoleCheckBox.setEnabled( false ); + } + }else{ + this.referrerRoleCheckBox.setSelection( false ); + this.referrerRolePropertyLabel.setEnabled(false); + this.referrerRolePropertyField.setEditable(false); + this.referrerRolePropertyField.setText(""); + this.referrerRoleCascadeField.setEnabled(false); + } + + AssociationRole referencedRole = association.getReferencedRole(); + if( referencedRole != null){ + this.referencedRoleCheckBox.setSelection( true ); + this.referencedRolePropertyLabel.setEnabled(true); + this.referencedRolePropertyField.setEditable(true); + this.referencedRolePropertyField.setText(referencedRole.getPropertyName()); + this.referencedRoleCascadeField.setEnabled(true); + String cascade = referencedRole.getCascade(); + if( cascade!=null ) + this.referencedRoleCascadeField.setText(cascade); + }else{ + this.referencedRoleCheckBox.setSelection( false ); + this.referencedRolePropertyLabel.setEnabled(false); + this.referencedRolePropertyField.setEditable(false); + this.referencedRolePropertyField.setText(""); + this.referencedRoleCascadeField.setEnabled(false); + } + + //Join conditions + updateJoinConditions(association, table1Name, table2Name, joinTableName); + } + + private void updateJoinConditions(Association association, + String table1Name, String table2Name, String joinTableName) { + String text = "%s"; + if( joinTableName == null ){ + StringBuilder strText = new StringBuilder(); + //text = JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen; + List<String> columnList1 = association.getReferrerColumnNames() ; + List<String> columnList2 = association.getReferencedColumnNames(); + for( int i=0; i < columnList1.size(); i++){ + strText.append( table1Name + "." + columnList1.get(i) );//$NON-NLS-1$ + strText.append( "=" );//$NON-NLS-1$ + strText.append( table2Name + "." + columnList2.get(i) );//$NON-NLS-1$ + if( i < columnList1.size()-1 ) + strText.append( "\n AND " );//$NON-NLS-1$ + } + joinConditionText.setText( String.format( text , strText.toString()) ); + }else{ + StringBuilder strText = new StringBuilder(); + //text = JptUiEntityGenMessages.GenerateEntitiesWizard_assocEditor_joinedWhen; + List<String> columnList1 = association.getReferrerColumnNames() ; + List<String> joinColumnList1 = association.getReferrerJoinColumnNames() ; + for( int i=0; i < columnList1.size(); i++){ + strText.append( table1Name + "." + columnList1.get(i) );//$NON-NLS-1$ + strText.append( "=" );//$NON-NLS-1$ + strText.append( joinTableName + "." + joinColumnList1.get(i) ); + strText.append( "\n AND " );//$NON-NLS-1$ + } + + List<String> joinTableColumnList2 = association.getReferencedJoinColumnNames(); + List<String> columnList2 = association.getReferencedColumnNames(); + for( int i=0; i < joinTableColumnList2.size(); i++){ + strText.append( joinTableName + "." + joinTableColumnList2.get(i) ); + strText.append( "=" );//$NON-NLS-1$ + strText.append( table2Name + "." + columnList2.get(i) );//$NON-NLS-1$ + if( i < joinTableColumnList2.size()-1 ) + strText.append( "\n AND " );//$NON-NLS-1$ + } + + joinConditionText.setText( String.format( text , strText.toString()) ); + + } + } + + /** + * Called when one of referrerRoleCheckBox or referencedRoleCheckBox + * changes value. + * + */ + private void directionalityCheckBoxChanged() { + String dir; + if (referrerRoleCheckBox.getSelection()) { + dir = referencedRoleCheckBox.getSelection() ? Association.BI_DI : Association.NORMAL_DI; + } else { + if (referencedRoleCheckBox.getSelection()) { + dir = Association.OPPOSITE_DI; + } else { + dir = null; + } + } + if (dir != null) { + selectedAssociation.setDirectionality(dir); + } else { + selectedAssociation.setGenerated(false); + } + + this.associationList.updateSelectedAssociation(); + } + + private ORMGenCustomizer getCustomizer(){ + GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard(); + return wizard.getCustomizer(); + } + + + @Override + public final void performHelp() + { + PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID ); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java new file mode 100644 index 0000000000..7fd0e75a64 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableFigure.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import org.eclipse.draw2d.ColorConstants; +import org.eclipse.draw2d.Figure; +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.GridLayout; +import org.eclipse.draw2d.Label; +import org.eclipse.draw2d.LineBorder; +import org.eclipse.draw2d.PositionConstants; +import org.eclipse.draw2d.geometry.Insets; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; + +/** + * A draw2D figure representing a database table + * + */ +public class TableFigure extends Figure { + public static Color tableColor = new Color(null,220,232,241); + public static Font tableFont = new Font(null, "Arial", 8, SWT.NONE); + public static Color disabledColor = ColorConstants.white; + public static Color borderColor = new Color( null, 14,66,115); + + public static final int OUTLINE_CORNER_RADIUS = 6; + + public TableFigure(String name) { + GridLayout gl = new GridLayout(); + gl.marginHeight = 2; + gl.marginWidth = 10; + setLayoutManager(gl); + + setBorder(new LineBorder(tableColor,0)); + setBackgroundColor(tableColor); + setOpaque(true); + setSize(150, 20); + + Label nameLabel = new Label("", CommonImages.createImage( CommonImages.TABLE_OBJ_IMAGE)); + nameLabel.setFont(tableFont); + nameLabel.setText(name); + nameLabel.setForegroundColor(borderColor); + nameLabel.setLabelAlignment(PositionConstants.CENTER); + add(nameLabel); + } + + protected void paintClientArea(Graphics graphics) + { + super.paintClientArea(graphics); + graphics.pushState(); + Rectangle r = getBounds().getCopy(); + graphics.drawRoundRectangle(r.expand(new Insets(-1, -1, -2, -2)), + OUTLINE_CORNER_RADIUS, OUTLINE_CORNER_RADIUS ); + graphics.popState(); + } + + public void setEnabled(boolean enabled ) { + super.setEnabled(enabled); + if( enabled ){ + setBackgroundColor(tableColor); + }else{ + setBackgroundColor(disabledColor); + } + } +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java new file mode 100644 index 0000000000..c0c4293cc7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TableGenPanel.java @@ -0,0 +1,393 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.List; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.JavaConventions; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.gen.internal2.ORMGenTable; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * The UI panel for setting the default and specific + * table entity generation properties. + * + */ +class TableGenPanel +{ + WizardPage wizardPage ; + + private Text classNameField; // used in setting individual table/entity generation only + + private Combo idGeneratorCombo; + private Text sequenceNameField; + + private Button entityAccessField; + private Button entityAccessProperty; + private Button associationFetchEager; + private Button associationFetchLazy; + + private Button collectionTypeSet; + private Button collectionTypeList; + + private Button generateOptionalAnnotations; + + private Label sequenceNameNoteLabel; + + private boolean isUpdatingControls; + + private ORMGenTable mTable; + + private boolean isDefaultTable = false; + + private static Color NOTE_LABEL_COLOR = new Color( Display.getDefault(), 102,102,102); + + public TableGenPanel(Composite parent, int columns , boolean isDefaultTable, WizardPage wizardPage ){ + super(); + this.wizardPage = wizardPage; + this.isDefaultTable = isDefaultTable; + createTableMappingPropertiesGroup(parent, columns); + SWTUtil.createLabel(parent, 4, ""); + } + + protected void createTableMappingPropertiesGroup(Composite composite, int columns) { + Group parent = new Group(composite, SWT.NONE ); + parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_tableMapping); + parent.setLayout(new GridLayout(columns, false)); + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + parent.setLayoutData(layoutData); + + createClassNameControl(parent, columns); + + createIdGeneratorControls(parent, columns); + createEntityAccessControls(parent, columns); + + //AssociationFetch and CollectionType only available for default table generation + if( isDefaultTable ){ + createAssociationFetchControls(parent, columns); + createCollectionTypeControls(parent, columns); + createGenerateOptionalAnnotationControls(parent, columns); + } + } + + private void createGenerateOptionalAnnotationControls(Group parent, int columns) { + SWTUtil.createLabel(parent, 1, ""); + generateOptionalAnnotations = new Button(parent, SWT.CHECK ); + generateOptionalAnnotations.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations); + generateOptionalAnnotations.setToolTipText(JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_genOptionalAnnotations_desc); + + GridData gd = new GridData(); + gd.horizontalSpan = columns-1; + gd.horizontalIndent = 3 ; + generateOptionalAnnotations.setLayoutData(gd); + generateOptionalAnnotations.addSelectionListener(new SelectionListener(){ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + boolean selected = generateOptionalAnnotations.getSelection(); + mTable.setGenerateDDLAnnotations(selected); + } + }); + } + + private void createClassNameControl(Composite parent, int columns) { + //Customize class name for specific table only + if( !isDefaultTable ){ + SWTUtil.createLabel( parent, 1 , JptUiEntityGenMessages.GenerateEntitiesWizard_tablePanel_className ); + + classNameField = new Text(parent, SWT.SINGLE | SWT.BORDER ); + //mPackageNameField.setEditable(false); + SWTUtil.fillColumns(classNameField,3); + classNameField.addModifyListener(new ModifyListener(){ + @SuppressWarnings({ "deprecation" }) + public void modifyText(ModifyEvent e) { + if (e.getSource() == null || !isUpdatingControls) { + String className = classNameField.getText(); + IStatus status = JavaConventions.validateJavaTypeName( className ); + if( !status.matches(IStatus.ERROR) ){ + mTable.setClassName( className ); + wizardPage.setErrorMessage(null); + }else{ + wizardPage.setErrorMessage(status.getMessage()); + } + } + } + }); + } + } + + class AssociationFetchListener implements SelectionListener{ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!isUpdatingControls) { + Button radioBtn = (Button)e.getSource(); + mTable.setDefaultFetch( radioBtn.getData().toString()); + } + } + } + + private void createAssociationFetchControls(Composite composite, int columns) { + SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_fetch ); + + Composite parent = new Composite( composite, SWT.NONE); + parent.setLayout(new RowLayout()); + SWTUtil.fillColumns( parent , 3); + + associationFetchEager = new Button( parent, SWT.RADIO ); + associationFetchEager.setText( "&Eager"); + associationFetchEager.setData( ORMGenTable.EAGER_FETCH ); + + associationFetchLazy = new Button( parent, SWT.RADIO ); + associationFetchLazy.setText( "La&zy"); + associationFetchLazy.setData( ORMGenTable.LAZY_FETCH ); + + AssociationFetchListener associationFetchListener = new AssociationFetchListener(); + associationFetchLazy.addSelectionListener( associationFetchListener ); + associationFetchEager.addSelectionListener( associationFetchListener ); + + } + + class CollectionTypeListener implements SelectionListener{ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!isUpdatingControls) { + Button radioBtn = (Button)e.getSource(); + mTable.setDefaultCollectionType( radioBtn.getData().toString()); + } + } + } + + private void createCollectionTypeControls(Composite composite, int columns){ + SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_collType ); + + Composite parent = new Composite( composite, SWT.NONE); + parent.setLayout(new RowLayout()); + SWTUtil.fillColumns( parent , 3); + + this.collectionTypeSet = new Button( parent, SWT.RADIO); + this.collectionTypeSet.setText( "java.util.Se&t"); + this.collectionTypeSet.setData( ORMGenTable.SET_COLLECTION_TYPE ); + this.collectionTypeList = new Button( parent, SWT.RADIO); + this.collectionTypeList.setText("java.util.&List"); + this.collectionTypeList.setData(ORMGenTable.LIST_COLLECTION_TYPE); + + CollectionTypeListener collectionTypeListener = new CollectionTypeListener(); + collectionTypeList.addSelectionListener( collectionTypeListener ); + collectionTypeSet.addSelectionListener( collectionTypeListener ); + + } + + + public void setORMGenTable(ORMGenTable table) { + mTable = table; + + isUpdatingControls = true; + + try { + //ClassNameField is not available for default table + if(classNameField!= null ) + classNameField.setText( mTable.getClassName() ); + + final List<String> schemes = this.mTable.getCustomizer().getAllIdGenerators(); + String[] values = new String[schemes.size()]; + schemes.toArray(values); + idGeneratorCombo.setItems( values ); + idGeneratorCombo.setText( mTable.getIdGenerator()); + + String sequenceName = mTable.isDefaultsTable() ? mTable.getSequence() : mTable.getFormattedSequence(); + sequenceName = ( sequenceName==null?"":sequenceName ); + sequenceNameField.setText( sequenceName ); + if( sequenceName.length()> 0 ){ + sequenceNameField.setEnabled(true); + sequenceNameNoteLabel.setEnabled(true); + }else{ + sequenceNameField.setEnabled(false); + sequenceNameNoteLabel.setEnabled(false); + } + + String access = mTable.getAccess() ; + if( ORMGenTable.FIELD_ACCESS.equals( access ) ){ + this.entityAccessField.setSelection( true ); + }else{ + this.entityAccessProperty.setSelection( true ); + } + + if(associationFetchLazy!=null && associationFetchEager != null ){ + String defaultFetch = mTable.getDefaultFetch(); + if( ORMGenTable.EAGER_FETCH.equals( defaultFetch ) ) + associationFetchEager.setSelection(true); + else + associationFetchLazy.setSelection(true); + } + + //DefautlTable only + if(collectionTypeList!=null){ + String cType = mTable.getDefaultCollectionType(); + if( ORMGenTable.LIST_COLLECTION_TYPE.equals( cType ) ){ + this.collectionTypeList.setSelection( true ); + }else{ + this.collectionTypeSet.setSelection( true ); + } + + this.generateOptionalAnnotations.setSelection( mTable.isGenerateDDLAnnotations()); + } + + } catch (Exception e) { + JptUiPlugin.log(e); + } + + isUpdatingControls = false; + } + + private void createIdGeneratorControls(Composite parent, int columns) { + SWTUtil.createLabel(parent, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_keyGen ); + + idGeneratorCombo = new Combo(parent,SWT.SINGLE | SWT.READ_ONLY); + SWTUtil.fillColumns(idGeneratorCombo,3); + + idGeneratorCombo.addSelectionListener( new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + if (isUpdatingControls) { + return; + } + + idGenChanged(); + }}); + + SWTUtil.createLabel(parent, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_sequence ); + sequenceNameField = new Text( parent, SWT.SINGLE | SWT.BORDER ); + + SWTUtil.fillColumns(sequenceNameField, 3); + sequenceNameField.addModifyListener(new ModifyListener(){ + public void modifyText(ModifyEvent e) { + if (e.getSource() == null || !isUpdatingControls) { + + if( idGeneratorCombo.getText().equals("sequence")){ + String sequenceName = sequenceNameField.getText(); + if( sequenceName.toLowerCase().indexOf("$table")>=0 || + sequenceName.toLowerCase().indexOf("$pk")>=0 ){ + sequenceName = convertVarToLowerCase("$table", sequenceName); + sequenceName = convertVarToLowerCase("$pk", sequenceName); + } + if( sequenceName.trim().length() != 0 ){ + mTable.setSeqence( sequenceName ); + wizardPage.setErrorMessage(null); + wizardPage.setPageComplete(true); + }else{ + wizardPage.setErrorMessage("Please specify a sequence name."); + wizardPage.setPageComplete(false); + } + }else{ + wizardPage.setErrorMessage(null); + wizardPage.setPageComplete(true); + } + } + } + + private String convertVarToLowerCase(String var, String sequenceName) { + int n = sequenceName.toLowerCase().indexOf( var ); + if( n==0 ){ + return var + sequenceName.substring( var.length()); + }else if( n >0 ){ + return sequenceName.substring(0,n) + var + sequenceName.substring( n + var.length()); + } + return sequenceName; + } + }); + + SWTUtil.newLabel(parent, "");//$NON-NLS-1$ + sequenceNameNoteLabel = new Label(parent, SWT.NONE); + String text =String.format( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_sequenceNote, + ORMGenTable.TABLE_SEQ_PATTERN, ORMGenTable.PK_SEQ_PATTERN); + sequenceNameNoteLabel.setText( text ) ; + sequenceNameNoteLabel.setEnabled(false); + SWTUtil.fillColumns( sequenceNameNoteLabel, 3); + } + + private void idGenChanged() { + String scheme = (String)idGeneratorCombo.getText(); + mTable.setIdGenerator(scheme); + + boolean isSequence = this.mTable.getCustomizer().getSequenceIdGenerators().contains(scheme); + if (!isSequence) { + sequenceNameField.setText(""); + sequenceNameField.setEnabled(false); + mTable.setSeqence(null); + sequenceNameNoteLabel.setEnabled(false); + }else{ + sequenceNameField.setEnabled(true); + sequenceNameNoteLabel.setForeground( NOTE_LABEL_COLOR ); + sequenceNameNoteLabel.setEnabled(true); + if( sequenceNameField.getText().length()==0 ) { + String newMessage = "Please specify a sequence name"; + this.wizardPage.setErrorMessage(newMessage); + this.wizardPage.setPageComplete(false); + }else{ + this.wizardPage.setErrorMessage(null); + this.wizardPage.setPageComplete(true); + } + } + } + + class EntityAccessFetchListener implements SelectionListener{ + public void widgetDefaultSelected(SelectionEvent e) {} + public void widgetSelected(SelectionEvent e) { + if (!isUpdatingControls) { + Button radioBtn = (Button)e.getSource(); + mTable.setAccess( radioBtn.getData().toString() ); + } + } + } + + private void createEntityAccessControls(Composite composite, int columns) { + SWTUtil.createLabel(composite, 1, JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_access ); + + Composite parent = new Composite( composite, SWT.NONE); + SWTUtil.fillColumns( parent , 3); + parent.setLayout(new RowLayout()); + + entityAccessField = new Button( parent, SWT.RADIO ); + entityAccessField.setText( "&Field" ); //$NON-NLS1$ + entityAccessField.setData( ORMGenTable.FIELD_ACCESS); + + entityAccessProperty = new Button( parent, SWT.RADIO ); + entityAccessProperty.setText( "&Property" );//$NON-NLS1$ + entityAccessProperty.setData( ORMGenTable.PROPERTY_ACCESS ); + + EntityAccessFetchListener entityAccessFetchListener = new EntityAccessFetchListener(); + entityAccessField.addSelectionListener( entityAccessFetchListener ); + entityAccessProperty.addSelectionListener( entityAccessFetchListener ); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java new file mode 100644 index 0000000000..c51ef8ad58 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesAndColumnsCustomizationWizardPage.java @@ -0,0 +1,351 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.ui.wizards.NewTypeWizardPage; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.gen.internal2.ORMGenColumn; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.gen.internal2.ORMGenTable; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.PlatformUI; + +public class TablesAndColumnsCustomizationWizardPage extends NewTypeWizardPage { + + @SuppressWarnings("unused") + private JpaProject jpaProject; + + private TreeViewer tableColumnTreeViewer ; + + private Composite detailPanel ; + private StackLayout detailPanelStatckLayout ; + private Composite tableGenDetatilGroup; + private ColumnGenPanel columnGenPanel; + private Composite columnGenDetatilGroup; + private TableGenPanel tableGenPanel; + private ORMGenTable selectedTable; + + private ORMGenCustomizer customizer; + + protected TablesAndColumnsCustomizationWizardPage(JpaProject jpaProject ) { + super(true, "TablesAndColumnsCustomizationWizardPage"); //$NON-NLS-1$ + this.jpaProject = jpaProject; + setTitle( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_title ); + setMessage( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_desc); + } + + // -------- Initialization --------- + /** + * The wizard owning this page is responsible for calling this method with the + * current selection. The selection is used to initialize the fields of the wizard + * page. + * + * @param selection used to initialize the fields + */ + void init(IStructuredSelection selection) { + if( jpaProject != null ){ + IJavaElement jelem = this.jpaProject.getJavaProject(); + initContainerPage(jelem); + initTypePage(jelem); + } + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 1 ; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.DIALOG_GENERATE_ENTITIES); + + createTableAndColumnsListPanel(composite, 1); + + SWTUtil.createLabel( composite, 1, ""); //$NON-NLS-1$ + + SWTUtil.createSeparator(composite, 1); + + createGenerateDetailGroup(composite, 1); + + setControl(composite); + this.setPageComplete( true ); + } + + /** + * A panel with JFace TreeViewer showing tables and columns to be generated into JPA entities + * + * @param parent + * @param columns + */ + private void createTableAndColumnsListPanel(Composite parent, int columns) { + Label label = new Label(parent, columns ); + label.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_tablesAndColumnsPage_labelTableAndColumns ); + SWTUtil.fillColumns( label , columns); + + GridData data = new GridData(); + data.horizontalSpan = columns; + data.verticalAlignment = SWT.FILL; + data.horizontalAlignment = SWT.FILL; + data.grabExcessHorizontalSpace = true; + data.heightHint = 200; + data.grabExcessVerticalSpace = true; + + tableColumnTreeViewer = new TreeViewer(parent); + tableColumnTreeViewer.getTree().setLayoutData( data); + tableColumnTreeViewer.setContentProvider(new TableColumnTreeContentProvider()); + tableColumnTreeViewer.setLabelProvider(new TableColumnTreeLabelProvider()); + + tableColumnTreeViewer.addSelectionChangedListener( new ISelectionChangedListener(){ + public void selectionChanged(SelectionChangedEvent event) { + updateDetailPanel(event.getSelection()); + } + + }); + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + if(visible){ + ORMGenCustomizer customizer = getCustomizer(); + //If user changed the connection or schema + if( this.customizer != customizer ){ + this.customizer = customizer; + tableColumnTreeViewer.setInput( customizer ); + }else{ + tableColumnTreeViewer.refresh(); + } + List<String> tableNames = this.customizer.getTableNames(); + + //Select the first table + ORMGenTable ormGenTable = this.customizer.getTable(tableNames.get(0)); + updateTabelGenDetail( ormGenTable ); + } + } + + + private void updateDetailPanel(ISelection selection) { + TreeSelection ts = (TreeSelection)selection; + Object selectedObject = ts.getFirstElement(); + if( selectedObject instanceof ORMGenTable ){ + updateTabelGenDetail( (ORMGenTable)selectedObject ); + }else if( selectedObject instanceof ORMGenColumn ){ + updateColumnGenDetail( (ORMGenColumn)selectedObject ); + } + } + + private void updateColumnGenDetail(ORMGenColumn column) { + if(columnGenDetatilGroup==null){ + columnGenDetatilGroup = new Composite(detailPanel, SWT.NONE); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 4; + columnGenDetatilGroup.setLayout(gridLayout); + this.columnGenPanel = new ColumnGenPanel(columnGenDetatilGroup, 4, getCustomizer() , this ); + } + columnGenPanel.setColumn(column); + this.detailPanelStatckLayout.topControl = columnGenDetatilGroup; + this.detailPanel.layout(); + detailPanel.getParent().layout(); + } + + private void updateTabelGenDetail(ORMGenTable table) { + this.selectedTable = table; + if(tableGenDetatilGroup==null){ + tableGenDetatilGroup = new Composite(detailPanel, SWT.NONE); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 4; + tableGenDetatilGroup.setLayout(gridLayout); + + this.tableGenPanel = new TableGenPanel(tableGenDetatilGroup, 4 , false, this ); + createDomainJavaClassesPropertiesGroup(tableGenDetatilGroup, 4 ); + } + tableGenPanel.setORMGenTable(table); + + this.detailPanelStatckLayout.topControl = tableGenDetatilGroup; + this.detailPanel.layout(); + + String baseClass = table.getExtends(); + if( baseClass!= null ) + setSuperClass(baseClass, true); + + setSuperInterfaces( table.getImplements(), true); + + detailPanel.getParent().layout(); + } + + protected void createDomainJavaClassesPropertiesGroup(Composite composite, int columns) { + Group parent = new Group( composite, SWT.NONE); + parent.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_defaultTablePage_domainJavaClass ); + parent.setLayout(new GridLayout(columns, false)); + SWTUtil.fillColumns( parent, columns); + + createSuperClassControls(parent, columns); + createSuperInterfacesControls(parent, columns); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#superClassChanged() + */ + protected IStatus superClassChanged() { + IStatus status = super.superClassChanged(); + String baseClass = getSuperClass(); + if(baseClass!=null && this.selectedTable!=null ){ + String oldBaseClass = this.selectedTable.getExtends(); + if( !oldBaseClass.equals(baseClass )) + this.selectedTable.setExtends(baseClass); + } + return status; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.ui.wizards.NewTypeWizardPage#addSuperInterface(java.lang.String) + */ + @SuppressWarnings("unchecked") + public boolean addSuperInterface(String superInterface) { + super.addSuperInterface(superInterface); + List interfaces = getSuperInterfaces(); + if(this.selectedTable!=null) + this.selectedTable.setImplements(interfaces); + return true; + } + + protected void handleFieldChanged(String fieldName) { + super.handleFieldChanged(fieldName); + if( this.fSuperClassStatus.matches(IStatus.ERROR)){ + updateStatus(fSuperClassStatus); + }else{ + setMessage("", IMessageProvider.NONE); + setErrorMessage(null); + } + + } + + private ORMGenCustomizer getCustomizer(){ + GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) this.getWizard(); + return wizard.getCustomizer(); + } + /** + * Content provider, and label provider for the DB Table/Column TreeViewer + * + */ + class TableColumnTreeContentProvider implements ITreeContentProvider { + public Object[] getElements(Object inputElement) { + if( inputElement instanceof ORMGenCustomizer ){ + ORMGenCustomizer input = (ORMGenCustomizer )inputElement; + List<String> tableNameList = input.getGenTableNames(); + List<ORMGenTable> ret = new ArrayList<ORMGenTable>(); + for(String t : tableNameList){ + ORMGenTable ormGenTable = getCustomizer().getTable( t ); + ret.add( ormGenTable ); + } + return ret.toArray(); + } + return new Object[]{}; + } + public Object[] getChildren(Object parentElement) { + if( parentElement instanceof ORMGenTable ){ + ORMGenTable table = (ORMGenTable) parentElement; + List<ORMGenColumn> columns = table.getColumns(); + List<ORMGenColumn> ret = new ArrayList<ORMGenColumn>(); + boolean isCompositePk = DTPUtil.getPrimaryKeyColumnNames(table.getDbTable()).size()>1; + for( ORMGenColumn col : columns){ + if( col.isForeignKey() ) + continue; + if( col.isPrimaryKey() && isCompositePk ){ + continue; + } + ret.add(col); + } + return ret.toArray(); + } + return new Object[]{}; + } + public Object getParent(Object element) { + if( element instanceof ORMGenColumn){ + return null; + } + return null; + } + public boolean hasChildren(Object element) { + return( element instanceof ORMGenTable ); + } + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} + public void dispose() {} + } + + class TableColumnTreeLabelProvider extends LabelProvider{ + + public Image getImage(Object element) { + if( element instanceof ORMGenTable ){ + return CommonImages.createImage( CommonImages.TABLE_IMAGE ); + }else if( element instanceof ORMGenColumn ){ + ORMGenColumn col = ( ORMGenColumn)element; + if( col.isPrimaryKey() ) + return CommonImages.createImage( CommonImages.COLUMN_KEY_IMAGE); + return CommonImages.createImage( CommonImages.COLUMN_IMAGE); + } + return null; + } + + + public String getText(Object element) { + if( element instanceof ORMGenTable ){ + return ((ORMGenTable)element).getName(); + }else if( element instanceof ORMGenColumn ){ + return ((ORMGenColumn)element).getName(); + } + return super.getText(element); + } + } + + private void createGenerateDetailGroup(Composite parent, int columns) { + detailPanel = new Composite(parent, SWT.NONE); + SWTUtil.fillColumns( detailPanel, columns); + + detailPanelStatckLayout = new StackLayout(); + detailPanel.setLayout(detailPanelStatckLayout); + + Composite emptyPanel = new Composite(detailPanel, SWT.NONE); + emptyPanel.setLayoutData(new GridData()); + + detailPanelStatckLayout.topControl = emptyPanel; + detailPanel.layout(); + } + + @Override + public final void performHelp() + { + PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID ); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java new file mode 100644 index 0000000000..30e05e850a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/gen/TablesSelectorWizardPage.java @@ -0,0 +1,533 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ + +package org.eclipse.jpt.ui.internal.wizards.gen; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.JptDbPlugin; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal2.Association; +import org.eclipse.jpt.gen.internal2.ORMGenColumn; +import org.eclipse.jpt.gen.internal2.ORMGenCustomizer; +import org.eclipse.jpt.gen.internal2.util.DTPUtil; +import org.eclipse.jpt.ui.CommonImages; +import org.eclipse.jpt.ui.JptUiPlugin; +import org.eclipse.jpt.ui.internal.JpaHelpContextIds; +import org.eclipse.jpt.ui.internal.JptUiMessages; +import org.eclipse.jpt.ui.internal.util.SWTUtil; +import org.eclipse.jpt.ui.internal.util.TableLayoutComposite; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.PlatformUI; + +class TablesSelectorWizardPage extends WizardPage{ + + private static final int TABLE_COLUMN_INDEX = 0; + private JpaProject jpaProject; + private Schema schema = null; + private ORMGenCustomizer customizer = null; + private boolean synchronizePersistenceXml = true; + + private DatabaseGroup databaseGroup; + private CheckboxTableViewer tableTable; + + TablesSelectorWizardPage(JpaProject jpaProject ) { + super("TablesSelectorWizardPage"); //$NON-NLS-1$ + this.jpaProject = jpaProject; + this.schema = jpaProject.getDefaultDbSchema(); + setTitle(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_selectTable ); + setMessage(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_chooseEntityTable ); + } + + public void setVisible(boolean visible) { + super.setVisible(visible); + } + + // -------- Provide access to wrapped DTP connection related classes --------- + ConnectionProfile getProjectConnectionProfile() { + String profileName = this.jpaProject.getDataSource().getConnectionProfileName(); + return this.connectionProfileNamed(profileName); + } + + ConnectionProfile connectionProfileNamed(String profileName) { + return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(profileName); + } + + Schema getSchema(){ + return this.schema; + } + + void setSchema(Schema s){ + this.schema = s; + } + + public Collection<Table> getTables() { + Schema schema = this.getSchema(); + if (schema != null && schema.getName() != null) { + return CollectionTools.collection(schema.tables()); + } + return Collections.<Table> emptyList(); + } + + + // -------- Initialization --------- + /** + * The wizard owning this page is responsible for calling this method with the + * current selection. The selection is used to initialize the fields of the wizard + * page. + * + * @param selection used to initialize the fields + */ + void init(IStructuredSelection selection) { + doStatusUpdate(); + } + + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + Composite composite = new Composite(parent, SWT.NULL); + int nColumns= 3; + GridLayout layout = new GridLayout(); + layout.numColumns = nColumns; + composite.setLayout(layout); + + this.databaseGroup = createDatabaseGroup(composite, 400); + + createTablesSelectionControl(composite, nColumns); + + //Filler column + new Label( composite, SWT.NONE); + + final Button synchronizeClassesCheckBox = new Button(composite, SWT.CHECK); + synchronizeClassesCheckBox.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_synchronizeClasses ); + synchronizeClassesCheckBox.setSelection(true); + synchronizeClassesCheckBox.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + setSynchronizePersistenceXml(synchronizeClassesCheckBox.getSelection()); + } + + }); + fillColumns( synchronizeClassesCheckBox, 2); + + + PlatformUI.getWorkbench().getHelpSystem().setHelp(this.tableTable.getControl(), JpaHelpContextIds.DIALOG_GENERATE_ENTITIES_TABLES); + + setControl(composite); + + setPageComplete(true); + } + + @Override + public void dispose() { + if (this.databaseGroup != null) + this.databaseGroup.dispose(); + super.dispose(); + } + + @Override + public IWizardPage getPreviousPage() { + IWizardPage prevPage = super.getPreviousPage(); + if (prevPage instanceof PromptJPAProjectWizardPage) + //Prevent going back to the PromptJPAProjectWizardPage + //if JPA project already selected + return prevPage.getPreviousPage(); + else + return prevPage; + } + + private DatabaseGroup createDatabaseGroup(Composite parent, int widthHint) { + DatabaseGroup dbGroup = new DatabaseGroup(this.getContainer(), jpaProject, parent, widthHint); + /** + * listen for when the Database Connection changes its selected schema + * so we can keep the page in synch + */ + class DatabasePageListener implements DatabaseGroup.Listener { + public void selectedConnectionProfileChanged(ConnectionProfile connectionProfile) { + // ignore + jpaProject.getDataSource().setConnectionProfileName(connectionProfile.getName()); + JptCorePlugin.setConnectionProfileName(jpaProject.getProject(), connectionProfile.getName()); + + } + @SuppressWarnings("unchecked") + public void selectedSchemaChanged(Schema schema) { + if( schema==null ){ + updateTablesListViewer(Collections.EMPTY_LIST ); + doStatusUpdate(); + return; + } + jpaProject.setUserOverrideDefaultSchema(schema.getName()); + setSchema( schema ); + updateTablesSelector(schema); + } + } + dbGroup.addListener(new DatabasePageListener()); + dbGroup.init(); + return dbGroup; + } + + boolean synchronizePersistenceXml() { + return this.synchronizePersistenceXml; + } + + private void setSynchronizePersistenceXml(boolean synchronizePersistenceXml){ + this.synchronizePersistenceXml = synchronizePersistenceXml; + } + + private void selectAllTables(){ + this.tableTable.setAllChecked(true); + doStatusUpdate(); + } + + private void deselectAllTables(){ + this.tableTable.setAllChecked(false); + doStatusUpdate(); + } + + private void initTablesSelectionControl(Collection<Table> possibleTables) { + this.tableTable.setInput(possibleTables); + } + + private void createTablesSelectionControl(Composite parent, int columns) { + Label tableLabel = new Label(parent, SWT.NONE); + GridData gd= new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.verticalAlignment = GridData.BEGINNING; + tableLabel.setLayoutData( gd ); + tableLabel.setText( JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_tables ); + + TableLayoutComposite layout= new TableLayoutComposite(parent, SWT.NONE); + addColumnLayoutData(layout); + + final org.eclipse.swt.widgets.Table table = new org.eclipse.swt.widgets.Table(layout, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER | SWT.CHECK); + + TableColumn tableNameColumn = new TableColumn(table, SWT.NONE, TABLE_COLUMN_INDEX); + tableNameColumn.setText(JptUiEntityGenMessages.GenerateEntitiesWizard_tableSelectPage_tableColumn ); + tableNameColumn.setResizable(true); + + gd= new GridData(GridData.FILL_BOTH); + gd.heightHint= SWTUtil.getTableHeightHint(table, 20); + gd.widthHint = 250; + gd.grabExcessHorizontalSpace = true; + gd.grabExcessVerticalSpace = true ; + layout.setLayoutData(gd); + layout.setBackground(new Color( Display.getDefault(), 255, 0,0)); + + this.tableTable = new CheckboxTableViewer(table); + this.tableTable.setUseHashlookup(true); + this.tableTable.setLabelProvider(this.buildTableTableLabelProvider()); + this.tableTable.setContentProvider(this.buildTableTableContentProvider()); + this.tableTable.setSorter(new ViewerSorter() { + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + return ((Table) e1).getName().compareTo(((Table) e2).getName()); + } + }); + + this.tableTable.addPostSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + handleTablesListSelectionChanged(event); + } + }); + + table.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.F2 && e.stateMask == SWT.NONE) { + editEntityNameIfPossible(); + e.doit= false; + } + } + }); + + + updateTablesSelector( databaseGroup.getSelectedSchema() ); + + createButtonComposite(parent); + + GenerateEntitiesFromSchemaWizard generateEntitiesWizard = ((GenerateEntitiesFromSchemaWizard)this.getWizard()); + Collection<Table> possibleTables = generateEntitiesWizard.getPossibleTables(); + + initTablesSelectionControl(possibleTables); + } + + private void createButtonComposite(Composite parent){ + + Composite buttonComposite = new Composite(parent, SWT.NULL); + GridLayout buttonLayout = new GridLayout(1, false); + buttonComposite.setLayout(buttonLayout); + GridData data = new GridData(); + data.horizontalAlignment = GridData.FILL; + data.verticalAlignment = GridData.BEGINNING; + buttonComposite.setLayoutData(data); + + Button selectAllButton = new Button(buttonComposite, SWT.PUSH); + selectAllButton.setToolTipText(JptUiMessages.General_selectAll); + selectAllButton.setImage( CommonImages.createImage(CommonImages.DESC_BUTTON_SELECT_ALL) ); + GridData gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + selectAllButton.setLayoutData(gridData); + selectAllButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + selectAllTables(); + } + }); + + Button deselectAllButton = new Button(buttonComposite, SWT.PUSH); + deselectAllButton.setToolTipText(JptUiMessages.General_deselectAll); + deselectAllButton.setImage( CommonImages.createImage(CommonImages.DESC_BUTTON_DESELECT_ALL) ); + gridData = new GridData(); + gridData.horizontalAlignment = GridData.FILL; + deselectAllButton.setLayoutData(gridData); + deselectAllButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) {} + + public void widgetSelected(SelectionEvent e) { + deselectAllTables(); + } + }); + } + + + private void addColumnLayoutData(TableLayoutComposite layout) { + layout.addColumnData(new ColumnWeightData(50, true)); + } + + void editEntityNameIfPossible(){ + Object[] selected = ((IStructuredSelection) this.tableTable.getSelection()).toArray(); + if (selected.length != 1) { + return; + } + } + + void handleTablesListSelectionChanged(SelectionChangedEvent event) { + doStatusUpdate(); + } + + private IBaseLabelProvider buildTableTableLabelProvider() { + return new TableTableLabelProvider(); + } + + private IContentProvider buildTableTableContentProvider() { + return new TableTableContentProvider(); + } + + + Collection<Table> getSelectedTables() { + ArrayList<Table> selectedTables = new ArrayList<Table>(); + for (Object selectedTable : this.tableTable.getCheckedElements()) + selectedTables.add((Table) selectedTable); + return selectedTables; + } + + private boolean hasTablesSelected() { + return (this.tableTable != null) ? (this.getSelectedTables().size() > 0) : false; + } + + void updateTablesListViewer(Collection<Table> possibleTables) { + if (this.tableTable != null) { + this.initTablesSelectionControl(possibleTables); + } + } + + /** + * Update the status line and the OK button according to the given status + */ + protected void doStatusUpdate() { + if ( ! this.hasTablesSelected()) { + this.setPageComplete(false); + }else{ + try{ + getContainer().run(false, false, new IRunnableWithProgress(){ + public void run( final IProgressMonitor monitor ) + throws InvocationTargetException, InterruptedException + { + monitor.beginTask("Updating", 10); + + Collection<Table> ret = getSelectedTables(); + ArrayList<String> tableNames = new ArrayList<String>(); + for( Table t : ret ){ + tableNames.add(t.getName()); + } + Schema schema = getSchema(); + if( schema == null ){ + return ; + } + customizer.setSchema(schema); + customizer.setTableNames(tableNames); + monitor.done(); + } + }); + } catch (Exception e) { + JptUiPlugin.log(e); + } + + setPageComplete(true); + } + } + + // ********** inner classes ********** + private class TableTableLabelProvider extends LabelProvider implements ITableLabelProvider { + + TableTableLabelProvider() { + super(); + } + + @Override + public String getText(Object element) { + return ((Table) element).getName(); + } + + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + public String getColumnText(Object element, int columnIndex) { + if (element == null) { + return null; + } + switch (columnIndex) { + case TABLE_COLUMN_INDEX: + return ((Table) element).getName(); + + } + throw new IllegalArgumentException("invalid column index: " + columnIndex);// $NON-NLS-1$ + } + + } + + + private class TableTableContentProvider implements IStructuredContentProvider { + + TableTableContentProvider() { + super(); + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } + + public void dispose() {} + + public Object[] getElements(Object inputElement) { + return ((Collection<?>) inputElement).toArray(); + } + + } + + private void updateTablesSelector(final Schema schema) { + if(schema ==null) + return; + this.jpaProject.setUserOverrideDefaultSchema( schema.getName()); + JptCorePlugin.setUserOverrideDefaultSchemaName(jpaProject.getProject(), schema.getName()); + + updateTablesListViewer( CollectionTools.collection(schema.tables())); + + //Create the ORMGenCustomizer + GenerateEntitiesFromSchemaWizard wizard = (GenerateEntitiesFromSchemaWizard) getWizard(); + customizer = wizard.createORMGenCustomizer( schema ); + + if( tableTable!=null && customizer != null ){ + restoreWizardState(); + } + doStatusUpdate(); + + } + + private boolean restoreWizardState(){ + boolean pageComplete = false; + List<String> preSelectedTableNames = this.customizer.getTableNames(); + if(preSelectedTableNames!=null && preSelectedTableNames.size()>0) { + Set<String> set = new HashSet<String>(); + for(String s : preSelectedTableNames ){ + set.add(s); + } + TableItem[] items = this.tableTable.getTable().getItems(); + for (int i = 0; i < items.length; ++i) { + TableItem item = items[i]; + org.eclipse.jpt.db.Table element = (org.eclipse.jpt.db.Table)item.getData(); + if (element != null) { + boolean check = set.contains(element.getName()); + // only set if different, to avoid flicker + if (item.getChecked() != check) { + item.setChecked(check); + pageComplete = true; + } + } + } + } + return pageComplete; + } + + + /** + * Set the layoutData of the input control to occupy specified number of columns + * @param c + * @param columns + */ + private void fillColumns(Control c, int columns){ + GridData layoutData = new GridData(); + layoutData.horizontalSpan = columns; + layoutData.verticalAlignment = SWT.FILL; + layoutData.horizontalAlignment = SWT.FILL; + layoutData.grabExcessHorizontalSpace = true; + layoutData.grabExcessVerticalSpace = false; + c.setLayoutData(layoutData); + return ; + } + + @Override + public final void performHelp() + { + PlatformUI.getWorkbench().getHelpSystem().displayHelp( GenerateEntitiesFromSchemaWizard.HELP_CONTEXT_ID ); + } +} |