diff options
author | bvosburgh | 2008-07-29 05:26:05 +0000 |
---|---|---|
committer | bvosburgh | 2008-07-29 05:26:05 +0000 |
commit | fecdb5e889d325b156b0bc69001d9d2dc8118b0b (patch) | |
tree | bfb4a5cd06d412c7bdcebd8c15eb2ef260e96b1a | |
parent | 8da36d199093bfb1d1d6b9081903217224d9ff0c (diff) | |
download | webtools.dali-fecdb5e889d325b156b0bc69001d9d2dc8118b0b.tar.gz webtools.dali-fecdb5e889d325b156b0bc69001d9d2dc8118b0b.tar.xz webtools.dali-fecdb5e889d325b156b0bc69001d9d2dc8118b0b.zip |
[242321] database case-sensitivity
155 files changed, 9640 insertions, 5018 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties index 45e706a3fc..4aef2fc5aa 100644 --- a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties +++ b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties @@ -1,15 +1,13 @@ -############################################################################### -# Copyright (c) 2007 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 +################################################################################ +# 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 -############################################################################### +# Oracle - initial API and implementation +################################################################################ -NONE=<None> VALIDATE_PROJECT_NOT_SPECIFIED=Project must be specified VALIDATE_SOURCE_FOLDER_NOT_SPECIFIED=Source folder must be specified VALIDATE_SOURCE_FOLDER_ILLEGAL=Source folder path is illegal diff --git a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties index 96b6ab8345..bf44bff3e9 100644 --- a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties +++ b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_validation.properties @@ -1,13 +1,12 @@ -############################################################################### -# Copyright (c) 2007 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 +################################################################################ +# 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 -############################################################################### +# Oracle - initial API and implementation +################################################################################ PROJECT_NO_CONNECTION=No connection specified for project. No database-specific validation will be performed. PROJECT_INACTIVE_CONNECTION=Connection \"{0}\" is not active. No validation will be done against the data source. diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/EntityGeneratorDatabaseAnnotationNameBuilder.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/EntityGeneratorDatabaseAnnotationNameBuilder.java new file mode 100644 index 0000000000..20fffae446 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/EntityGeneratorDatabaseAnnotationNameBuilder.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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.core; + +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 EntityGeneratorDatabaseAnnotationNameBuilder { + + /** + * 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); + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaDataSource.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaDataSource.java index 9cd640ce66..e02f4c0efc 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaDataSource.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaDataSource.java @@ -9,7 +9,13 @@ ******************************************************************************/ package org.eclipse.jpt.core; +import java.util.Iterator; + +import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.Database; +import org.eclipse.jpt.db.DatabaseObject; +import org.eclipse.jpt.db.Schema; /** * @@ -38,7 +44,7 @@ public interface JpaDataSource extends JpaNode { * ID string used when connectionProfileName property is changed * @see org.eclipse.jpt.utility.model.Model#addPropertyChangeListener(String, org.eclipse.jpt.utility.model.listener.PropertyChangeListener) */ - public static final String CONNECTION_PROFILE_NAME_PROPERTY = "connectionProfileName"; + public static final String CONNECTION_PROFILE_NAME_PROPERTY = "connectionProfileName"; //$NON-NLS-1$ /** * The data source's connection profile should never be null. @@ -50,12 +56,26 @@ public interface JpaDataSource extends JpaNode { * ID string used when connectionProfile property is changed * @see org.eclipse.jpt.utility.model.Model#addPropertyChangeListener(String, org.eclipse.jpt.utility.model.listener.PropertyChangeListener) */ - public static final String CONNECTION_PROFILE_PROPERTY = "connectionProfile"; + public static final String CONNECTION_PROFILE_PROPERTY = "connectionProfile"; //$NON-NLS-1$ boolean connectionProfileIsActive(); - boolean hasAConnection(); + Database getDatabase(); + + Iterator<String> catalogNames(); + + Catalog getCatalogNamed(String name); + + Catalog getDefaultCatalog(); + Iterator<String> schemaNames(); + + Schema getSchemaNamed(String name); + + Schema getDefaultSchema(); + + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name); + void dispose(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaPlatform.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaPlatform.java index 7ebc79fbf4..2475db24c4 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaPlatform.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaPlatform.java @@ -10,11 +10,14 @@ package org.eclipse.jpt.core; import java.util.List; + import org.eclipse.core.resources.IFile; import org.eclipse.jpt.core.context.java.JavaAttributeMapping; import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; import org.eclipse.jpt.core.context.java.JavaPersistentType; import org.eclipse.jpt.core.context.java.JavaTypeMapping; +import org.eclipse.jpt.db.ConnectionProfileFactory; +import org.eclipse.jpt.db.DatabaseFinder; import org.eclipse.wst.validation.internal.provisional.core.IMessage; /** @@ -52,7 +55,7 @@ public interface JpaPlatform void setId(String theId); - // **************** Model construction / updating ************************** + // **************** Model construction/updating ************************** /** * Construct a JPA file for the specified file, to be added to the specified @@ -79,12 +82,12 @@ public interface JpaPlatform JpaAnnotationProvider getAnnotationProvider(); - // **************** Java type mapping support ******************************** + // **************** Java type mapping providers ******************************** /** * Build a Java type mapping with the given mapping key and parent. Throws a IllegalArgumentException * if the typeMappingKey is not supported by this platform. - * Override {@link #GenericJpaPlatform.addJavaTypeMappingProvidersTo(Collection<JavaTypeMappingProvider>)} + * Override {@link org.eclipse.jpt.core.internal.platform.GenericJpaPlatform#addJavaTypeMappingProvidersTo(List<JavaTypeMappingProvider>)} * to add new supported type mappings to the platform */ JavaTypeMapping buildJavaTypeMappingFromMappingKey(String typeMappingKey, JavaPersistentType parent); @@ -92,17 +95,18 @@ public interface JpaPlatform /** * Build a Java type mapping with the given mapping annotation and parent. Throws a IllegalArgumentException * if the mapping annotation is not supported by this platform. - * Override {@link #GenericJpaPlatform.addJavaTypeMappingProvidersTo(Collection<JavaTypeMappingProvider>)} + * Override {@link org.eclipse.jpt.core.internal.platform.GenericJpaPlatform#addJavaTypeMappingProvidersTo(List<JavaTypeMappingProvider>)} * to add new supported type mappings to the platform */ JavaTypeMapping buildJavaTypeMappingFromAnnotation(String mappingAnnotationName, JavaPersistentType parent); - // **************** Java attribute mapping support ******************************** + + // **************** Java attribute mapping providers ******************************** /** * Build a Java attribute mapping with the given mapping key and parent. Throws a IllegalArgumentException * if the attributeMappingKey is not supported by this platform. - * Override {@link #GenericJpaPlatform.addJavaAttributeMappingProvidersTo(Collection<JavaAttributeMappingProvider>)} + * Override {@link org.eclipse.jpt.core.internal.platform.GenericJpaPlatform#addJavaAttributeMappingProvidersTo(List<JavaAttributeMappingProvider>)} * to add new supported attribute mappings to the platform */ JavaAttributeMapping buildJavaAttributeMappingFromMappingKey(String attributeMappingKey, JavaPersistentAttribute parent); @@ -110,7 +114,7 @@ public interface JpaPlatform /** * Build a Java attribute mapping with the given mapping annotation and parent. Throws a IllegalArgumentException * if the mapping annotation is not supported by this platform. - * Override {@link #GenericJpaPlatform.addJavaAttributeMappingProvidersTo(Collection<JavaAttributeMappingProvider>)} + * Override {@link org.eclipse.jpt.core.internal.platform.GenericJpaPlatform#addJavaAttributeMappingProvidersTo(List<JavaAttributeMappingProvider>)} * to add new supported attribute mappings to the platform */ JavaAttributeMapping buildJavaAttributeMappingFromAnnotation(String mappingAnnotationName, JavaPersistentAttribute parent); @@ -118,7 +122,7 @@ public interface JpaPlatform /** * Build a default Java attribute mapping with the given mapping annotation and parent. Throws a IllegalArgumentException * if the mapping annotation is not supported by this platform. - * Override {@link #GenericJpaPlatform.addDefaultJavaAttributeMappingProvidersTo(Collection<DefaultJavaAttributeMappingProvider>)} + * Override {@link org.eclipse.jpt.core.internal.platform.GenericJpaPlatform#addDefaultJavaAttributeMappingProvidersTo(List<DefaultJavaAttributeMappingProvider>)} * to add new supported attribute mappings to the platform */ JavaAttributeMapping buildDefaultJavaAttributeMapping(JavaPersistentAttribute parent); @@ -126,15 +130,39 @@ public interface JpaPlatform /** * Return the attribute mapping key corresponding to the default atribute mapping * that applies to the Java persistent attribute. This will be based on the attribute's - * type. See {@link DefaultJavaAttributeMappingProvider.#defaultApplies(JavaPersistentAttribute)} + * type. See {@link org.eclipse.jpt.core.context.java.DefaultJavaAttributeMappingProvider#defaultApplies(JavaPersistentAttribute)} */ - String defaultJavaAttributeMappingKey(JavaPersistentAttribute persistentAttribute); - - // ************************************************************************* + String getDefaultJavaAttributeMappingKey(JavaPersistentAttribute persistentAttribute); + + + // ************** Validation *********************************************************** /** * Adds validation messages to the growing list of messages for a given project */ void addToMessages(JpaProject project, List<IMessage> messages); + + // ************* Database ************************************************************ + + /** + * Return a connection repository that can be used to query the database + * about database metadata. + */ + ConnectionProfileFactory getConnectionProfileFactory(); + + /** + * Return an entity generator database annotation name builder, which is + * used by Entity Generation to determine whether and how the entity generator + * prints the names of various database objects. + */ + EntityGeneratorDatabaseAnnotationNameBuilder getEntityGeneratorDatabaseAnnotationNameBuilder(); + + /** + * Return a finder that can be used to look up various objects (schemata, + * tables, columns, etc.) on the database, respecting the platform's and + * database's case-sensitivity. + */ + DatabaseFinder getDatabaseFinder(); + } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/RelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/RelationshipMapping.java index e4164dddb4..875392e0f5 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/RelationshipMapping.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/context/RelationshipMapping.java @@ -35,11 +35,6 @@ public interface RelationshipMapping extends AttributeMapping, Fetchable Entity getResolvedTargetEntity(); String RESOLVED_TARGET_ENTITY_PROPERTY = "resolvedTargetEntityProperty"; - /** - * Return whether the specified 'targetEntity' is valid. - */ - boolean targetEntityIsValid(String targetEntity); - // **************** cascade ************************************** diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaNode.java index cbc6bca2c4..31aede7d77 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaNode.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaNode.java @@ -12,16 +12,16 @@ package org.eclipse.jpt.core.internal; import java.util.HashMap; import java.util.HashSet; import java.util.Set; + import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Platform; +import org.eclipse.jpt.core.JpaDataSource; import org.eclipse.jpt.core.JpaFactory; import org.eclipse.jpt.core.JpaFile; import org.eclipse.jpt.core.JpaNode; import org.eclipse.jpt.core.JpaPlatform; import org.eclipse.jpt.core.JpaProject; import org.eclipse.jpt.core.ResourceModel; -import org.eclipse.jpt.db.ConnectionProfile; -import org.eclipse.jpt.db.Database; import org.eclipse.jpt.utility.internal.model.AbstractModel; import org.eclipse.jpt.utility.internal.model.CallbackChangeSupport; import org.eclipse.jpt.utility.internal.model.ChangeSupport; @@ -47,11 +47,11 @@ public abstract class AbstractJpaNode protected void checkParent(JpaNode p) { if (p == null) { if (this.requiresParent()) { - throw new IllegalArgumentException("'parent' cannot be null"); + throw new IllegalArgumentException("'parent' cannot be null"); //$NON-NLS-1$ } } else { if (this.forbidsParent()) { - throw new IllegalArgumentException("'parent' must be null"); + throw new IllegalArgumentException("'parent' must be null"); //$NON-NLS-1$ } } } @@ -108,21 +108,18 @@ public abstract class AbstractJpaNode } protected JpaFile getJpaFile(ResourceModel resourceModel) { - return getJpaProject().getJpaFile(resourceModel.getFile()); - } - - protected ConnectionProfile getConnectionProfile() { - return this.getJpaProject().getConnectionProfile(); + return this.getJpaProject().getJpaFile(resourceModel.getFile()); } - protected Database getDatabase() { - return this.getConnectionProfile().getDatabase(); + protected JpaDataSource getDataSource() { + return this.getJpaProject().getDataSource(); } public boolean connectionProfileIsActive() { - return this.getConnectionProfile().isActive(); + return this.getDataSource().connectionProfileIsActive(); } + // ********** update model ********** private static final HashMap<Class<? extends AbstractJpaNode>, HashSet<String>> nonUpdateAspectNameSets = new HashMap<Class<? extends AbstractJpaNode>, HashSet<String>>(); @@ -154,7 +151,7 @@ public abstract class AbstractJpaNode } } - protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) { + protected void addNonUpdateAspectNamesTo(@SuppressWarnings("unused") Set<String> nonUpdateAspectNames) { // when you override this method, don't forget to include: // super.addNonUpdateAspectNamesTo(nonUpdateAspectNames); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaDataSource.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaDataSource.java index 75295a050d..9b2d896545 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaDataSource.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaDataSource.java @@ -9,14 +9,19 @@ ******************************************************************************/ package org.eclipse.jpt.core.internal; +import java.util.Iterator; + import org.eclipse.jpt.core.JpaDataSource; import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.ConnectionAdapter; import org.eclipse.jpt.db.ConnectionListener; import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.ConnectionProfileFactory; import org.eclipse.jpt.db.ConnectionProfileListener; -import org.eclipse.jpt.db.ConnectionProfileRepository; -import org.eclipse.jpt.db.JptDbPlugin; +import org.eclipse.jpt.db.Database; +import org.eclipse.jpt.db.DatabaseObject; +import org.eclipse.jpt.db.Schema; /** * GenericJpaDataSource @@ -31,10 +36,6 @@ public class GenericJpaDataSource */ protected String connectionProfileName; - /** - * this should never be null; if we do not have a connection, this will be - * a "null" connection profile - */ protected transient ConnectionProfile connectionProfile; /** @@ -51,20 +52,22 @@ public class GenericJpaDataSource // ********** constructor/initialization ********** - private ConnectionProfileRepository getConnectionProfileRepository() { - return JptDbPlugin.instance().getConnectionProfileRepository(); - } - public GenericJpaDataSource(JpaProject jpaProject, String connectionProfileName) { super(jpaProject); this.connectionProfileListener = this.buildConnectionProfileListener(); - this.getConnectionProfileRepository().addConnectionProfileListener(this.connectionProfileListener); + this.getConnectionProfileFactory().addConnectionProfileListener(this.connectionProfileListener); this.connectionListener = this.buildConnectionListener(); this.connectionProfileName = connectionProfileName; - this.connectionProfile = this.connectionProfileNamed(connectionProfileName); - this.connectionProfile.addConnectionListener(this.connectionListener); + this.connectionProfile = this.buildConnectionProfile(connectionProfileName); + if (this.connectionProfile != null) { + this.connectionProfile.addConnectionListener(this.connectionListener); + } + } + + protected ConnectionProfileFactory getConnectionProfileFactory() { + return this.getJpaPlatform().getConnectionProfileFactory(); } protected ConnectionProfileListener buildConnectionProfileListener() { @@ -76,7 +79,7 @@ public class GenericJpaDataSource } - // ********** IJpaDataSource implementation ********** + // ********** JpaDataSource implementation ********** public String getConnectionProfileName() { return this.connectionProfileName; @@ -87,35 +90,82 @@ public class GenericJpaDataSource this.connectionProfileName = connectionProfileName; this.firePropertyChanged(CONNECTION_PROFILE_NAME_PROPERTY, old, connectionProfileName); // synch the connection profile when the name changes - this.setConnectionProfile(this.connectionProfileNamed(connectionProfileName)); + this.setConnectionProfile(this.buildConnectionProfile(connectionProfileName)); } - @Override public ConnectionProfile getConnectionProfile() { return this.connectionProfile; } - public boolean hasAConnection() { - return ! this.connectionProfile.isNull(); + @Override + public boolean connectionProfileIsActive() { + ConnectionProfile cp = this.connectionProfile; + return (cp != null) && cp.isActive(); + } + + public Database getDatabase() { + ConnectionProfile cp = this.connectionProfile; + return (cp == null) ? null : cp.getDatabase(); + } + + public Iterator<String> catalogNames() { + Database db = this.getDatabase(); + return (db == null) ? null : db.catalogNames(); + } + + public Catalog getCatalogNamed(String name) { + Database db = this.getDatabase(); + return (db == null) ? null : db.getCatalogNamed(name); + } + + public Catalog getDefaultCatalog() { + Database db = this.getDatabase(); + return (db == null) ? null : db.getDefaultCatalog(); + } + + public Iterator<String> schemaNames() { + Database db = this.getDatabase(); + return (db == null) ? null : db.schemaNames(); + } + + public Schema getSchemaNamed(String name) { + Database db = this.getDatabase(); + return (db == null) ? null : db.getSchemaNamed(name); + } + + public Schema getDefaultSchema() { + Database db = this.getDatabase(); + return (db == null) ? null : db.getDefaultSchema(); + } + + public <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name) { + Database db = this.getDatabase(); + return (db == null) ? null : db.getDatabaseObjectNamed(databaseObjects, name); } public void dispose() { - this.connectionProfile.removeConnectionListener(this.connectionListener); - this.getConnectionProfileRepository().removeConnectionProfileListener(this.connectionProfileListener); + if (this.connectionProfile != null) { + this.connectionProfile.removeConnectionListener(this.connectionListener); + } + this.getConnectionProfileFactory().removeConnectionProfileListener(this.connectionProfileListener); } // ********** internal methods ********** - private ConnectionProfile connectionProfileNamed(String name) { - return this.getConnectionProfileRepository().connectionProfileNamed(name); + protected ConnectionProfile buildConnectionProfile(String name) { + return this.getConnectionProfileFactory().buildConnectionProfile(name, this.getJpaPlatform().getDatabaseFinder()); } protected void setConnectionProfile(ConnectionProfile connectionProfile) { ConnectionProfile old = this.connectionProfile; - this.connectionProfile.removeConnectionListener(this.connectionListener); + if (old != null) { + old.removeConnectionListener(this.connectionListener); + } this.connectionProfile = connectionProfile; - this.connectionProfile.addConnectionListener(this.connectionListener); + if (connectionProfile != null) { + connectionProfile.addConnectionListener(this.connectionListener); + } this.firePropertyChanged(CONNECTION_PROFILE_PROPERTY, old, connectionProfile); } @@ -123,11 +173,6 @@ public class GenericJpaDataSource // ********** overrides ********** @Override - public boolean connectionProfileIsActive() { - return this.connectionProfile.isActive(); - } - - @Override public void toString(StringBuilder sb) { sb.append(this.connectionProfileName); } @@ -136,26 +181,42 @@ public class GenericJpaDataSource // ********** member classes ********** /** - * Listen for a connection profile with our name being added or removed. + * Listen for a connection profile with our name being removed. * Also listen for our connection's name being changed. */ protected class LocalConnectionProfileListener implements ConnectionProfileListener { + protected LocalConnectionProfileListener() { super(); } - // possible name change - public void connectionProfileChanged(ConnectionProfile profile) { - if (profile == GenericJpaDataSource.this.connectionProfile) { - GenericJpaDataSource.this.setConnectionProfileName(profile.getName()); + public void connectionProfileAdded(String name) { + // check to see if a connection profile with our name was added + // (assume our connection profile is null) + if (GenericJpaDataSource.this.connectionProfile == null) { + if (name.equals(GenericJpaDataSource.this.getConnectionProfileName())) { + GenericJpaDataSource.this.setConnectionProfileName(name); // this will trigger creation of CP + } } } - // profile added or removed - public void connectionProfileReplaced(ConnectionProfile oldProfile, ConnectionProfile newProfile) { - if (GenericJpaDataSource.this.hasAConnection() && - (oldProfile == GenericJpaDataSource.this.connectionProfile)) { - GenericJpaDataSource.this.setConnectionProfile(newProfile); + public void connectionProfileRemoved(String name) { + if (GenericJpaDataSource.this.connectionProfile == null) { + return; + } + if (name.equals(GenericJpaDataSource.this.connectionProfile.getName())) { + GenericJpaDataSource.this.setConnectionProfile(null); + } + } + + public void connectionProfileRenamed(String oldName, String newName) { + if (GenericJpaDataSource.this.connectionProfile == null) { + return; + } + // the connection profile will already have the new name, + // we just need to synch the name held by the data source + if (newName.equals(GenericJpaDataSource.this.connectionProfile.getName())) { + GenericJpaDataSource.this.setConnectionProfileName(newName); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java index da6eb5bc3e..25dce11802 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaProject.java @@ -242,28 +242,22 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { return this.jpaPlatform; } + @Override public JpaDataSource getDataSource() { return this.dataSource; } - @Override public ConnectionProfile getConnectionProfile() { return this.dataSource.getConnectionProfile(); } - + public Schema getDefaultSchema() { - Schema defaultSchema = getUserOverrideDefaultSchema(); - if (defaultSchema != null) { - return defaultSchema; - } - return getConnectionProfile().getDefaultSchema(); + Schema schema = this.getUserOverrideDefaultSchema(); + return (schema != null) ? schema : this.getDataSource().getDefaultSchema(); } public Schema getUserOverrideDefaultSchema() { - if (this.userOverrideDefaultSchemaName == null) { - return null; - } - return getConnectionProfile().getDatabase().schemaNamed(this.userOverrideDefaultSchemaName); + return (this.userOverrideDefaultSchemaName == null) ? null : this.getDataSource().getSchemaNamed(this.userOverrideDefaultSchemaName); } @@ -372,7 +366,7 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { jpaFile.getResourceModel().removeResourceModelChangeListener(this.resourceModelListener); jpaFile.dispose(); if ( ! this.removeItemFromCollection(jpaFile, this.jpaFiles, JPA_FILES_COLLECTION)) { - throw new IllegalArgumentException("JPA file: " + jpaFile.getFile().getName()); + throw new IllegalArgumentException("JPA file: " + jpaFile.getFile().getName()); //$NON-NLS-1$ } } @@ -493,7 +487,7 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { protected boolean okToProceedForConnectionValidation = true; protected void addNoConnectionMessage(List<IMessage> messages) { - if (! this.getDataSource().hasAConnection()) { + if (this.getConnectionProfile() == null) { messages.add( DefaultJpaValidationMessages.buildMessage( IMessage.NORMAL_SEVERITY, @@ -517,7 +511,7 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { okToProceedForConnectionValidation = true; } - protected void addMultiplePersistenceXmlMessage(List<IMessage> messages) { + protected void addMultiplePersistenceXmlMessage(@SuppressWarnings("unused") List<IMessage> messages) { // if (validPersistenceXmlFiles.size() > 1) { // messages.add( // JpaValidationMessages.buildMessage( @@ -535,7 +529,7 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { protected static final String WEB_PROJECT_ROOT_DEPLOY_LOCATION = J2EEConstants.WEB_INF_CLASSES; public String getRootDeployLocation() { - return this.isWebProject() ? WEB_PROJECT_ROOT_DEPLOY_LOCATION : ""; + return this.isWebProject() ? WEB_PROJECT_ROOT_DEPLOY_LOCATION : ""; //$NON-NLS-1$ } protected static final String JST_WEB_MODULE = IModuleConstants.JST_WEB_MODULE; @@ -688,7 +682,7 @@ public class GenericJpaProject extends AbstractJpaNode implements JpaProject { */ public void update() { if (this.updater == null) { - throw new IllegalStateException("updater is null, use setUpdater(Updater) after construction of GenericJpaProject"); + throw new IllegalStateException("updater is null, use #setUpdater(Updater) after construction of GenericJpaProject"); //$NON-NLS-1$ } this.updater.update(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java index 9a00d71134..ecab723abe 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java @@ -1,8 +1,8 @@ /******************************************************************************* * 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. + * 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 @@ -11,61 +11,42 @@ package org.eclipse.jpt.core.internal; import org.eclipse.osgi.util.NLS; -public class JptCoreMessages extends NLS -{ - private static final String BUNDLE_NAME = "jpa_core"; //$NON-NLS-1$ - - static { - // initialize resource bundle - NLS.initializeMessages(BUNDLE_NAME, JptCoreMessages.class); - } - +/** + * Localized messages used by Dali core. + */ +public class JptCoreMessages { + public static String NONE; - public static String VALIDATE_PROJECT_NOT_SPECIFIED; - public static String VALIDATE_SOURCE_FOLDER_NOT_SPECIFIED; - public static String VALIDATE_SOURCE_FOLDER_ILLEGAL; - public static String VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST; - public static String VALIDATE_SOURCE_FOLDER_NOT_IN_PROJECT; - public static String VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER; - public static String VALIDATE_ORM_FILE_ALREADY_EXISTS; - public static String VALIDATE_PERSISTENCE_UNIT_DOES_NOT_SPECIFIED; - public static String VALIDATE_PERSISTENCE_UNIT_NOT_IN_PROJECT; - public static String VALIDATE_PLATFORM_NOT_SPECIFIED; - public static String VALIDATE_CONNECTION_NOT_SPECIFIED; - public static String VALIDATE_CONNECTION_NOT_CONNECTED; - public static String VALIDATE_DEFAULT_SCHEMA_NOT_SPECIFIED; - public static String VALIDATE_RUNTIME_NOT_SPECIFIED; - public static String VALIDATE_RUNTIME_DOES_NOT_SUPPORT_EJB_30; - public static String VALIDATE_LIBRARY_NOT_SPECIFIED; - public static String SYNCHRONIZE_CLASSES_JOB; - public static String SYNCHRONIZING_CLASSES_TASK; - public static String INVALID_PERSISTENCE_XML_CONTENT; - public static String ERROR_SYNCHRONIZING_CLASSES_COULD_NOT_VALIDATE; - public static String ERROR_WRITING_FILE; - + + private static final String BUNDLE_NAME = "jpa_core"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptCoreMessages.class; + static { + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); + } private JptCoreMessages() { throw new UnsupportedOperationException(); } + } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/MappingTools.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/MappingTools.java index c19f5e3e63..e3cf890046 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/MappingTools.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/MappingTools.java @@ -10,7 +10,7 @@ package org.eclipse.jpt.core.internal.context; import java.util.Iterator; -import java.util.StringTokenizer; + import org.eclipse.jpt.core.MappingKeys; import org.eclipse.jpt.core.context.ColumnMapping; import org.eclipse.jpt.core.context.Embeddable; @@ -22,34 +22,7 @@ import org.eclipse.jpt.core.context.RelationshipMapping; import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; public class MappingTools -{ - public static boolean targetEntityIsValid(String targetEntity) { - if (targetEntity == null) { - return true; - } - // balance is # of name tokens - # of period tokens seen so far - // initially 0; finally 1; should never drop < 0 or > 1 - int balance = 0; - for (StringTokenizer t = new StringTokenizer(targetEntity, ".", true); t.hasMoreTokens();) { - String s = t.nextToken(); - if (s.indexOf('.') >= 0) { - // this is a delimiter - if (s.length() > 1) { - // too many periods in a row - return false; - } - balance--; - if (balance < 0) { - return false; - } - } else { - // this is an identifier segment - balance++; - } - } - return (balance == 1); - } - +{ /** * Default join table name from the JPA spec: * The concatenated names of the two associated primary @@ -73,7 +46,7 @@ public class MappingTools if (targetTableName == null) { return null; } - return owningTableName + "_" + targetTableName; + return owningTableName + '_' + targetTableName; } /** @@ -105,7 +78,7 @@ public class MappingTools if (targetColumn == null) { return null; } - return prefix + "_" + targetColumn; + return prefix + '_' + targetColumn; } /** diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaNamedColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaNamedColumn.java index 4e80363cbc..6e9551dbe4 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaNamedColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaNamedColumn.java @@ -129,7 +129,7 @@ public abstract class AbstractJavaNamedColumn<T extends NamedColumnAnnotation> e public Column getDbColumn() { Table table = this.getDbTable(); - return (table == null) ? null : table.columnNamed(this.getName()); + return (table == null) ? null : table.getColumnNamed(this.getName()); } public Table getDbTable() { @@ -169,6 +169,11 @@ public abstract class AbstractJavaNamedColumn<T extends NamedColumnAnnotation> e private Iterator<String> quotedCandidateNames(Filter<String> filter) { return StringTools.quote(this.candidateNames(filter)); } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.getName()); + } // ******************* update from java resource model ******************** diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaRelationshipMapping.java index 9be2b4b4b7..2fd7223d5a 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaRelationshipMapping.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaRelationshipMapping.java @@ -18,7 +18,6 @@ import org.eclipse.jpt.core.context.PersistentType; import org.eclipse.jpt.core.context.RelationshipMapping; import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; import org.eclipse.jpt.core.context.java.JavaRelationshipMapping; -import org.eclipse.jpt.core.internal.context.MappingTools; import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; import org.eclipse.jpt.core.resource.java.RelationshipMappingAnnotation; import org.eclipse.jpt.utility.Filter; @@ -189,10 +188,4 @@ public abstract class AbstractJavaRelationshipMapping<T extends RelationshipMapp return StringTools.quote(this.candidateMappedByAttributeNames(filter)); } - - // ********** static methods ********** - - public boolean targetEntityIsValid(String targetEntity) { - return MappingTools.targetEntityIsValid(targetEntity); - } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java index 6ce7369b2b..25acb008f5 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/AbstractJavaTable.java @@ -338,11 +338,11 @@ public abstract class AbstractJavaTable extends AbstractJavaJpaContextNode imple public org.eclipse.jpt.db.Table getDbTable() { Schema schema = this.getDbSchema(); - return (schema == null) ? null : schema.tableNamed(this.getName()); + return (schema == null) ? null : schema.getTableNamed(this.getName()); } public Schema getDbSchema() { - return this.getDatabase().schemaNamed(this.getSchema()); + return this.getDataSource().getSchemaNamed(this.getSchema()); } public boolean hasResolvedSchema() { @@ -404,7 +404,7 @@ public abstract class AbstractJavaTable extends AbstractJavaJpaContextNode imple } private Iterator<String> candidateSchemas() { - return this.getDatabase().schemaNames(); + return this.getDataSource().schemaNames(); } private Iterator<String> candidateSchemas(Filter<String> filter) { @@ -416,7 +416,7 @@ public abstract class AbstractJavaTable extends AbstractJavaJpaContextNode imple } private Iterator<String> candidateCatalogs() { - return this.getDatabase().catalogNames(); + return this.getDataSource().catalogNames(); } private Iterator<String> candidateCatalogs(Filter<String> filter) { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaEntity.java index 9faaa496ef..fdb39f4f57 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaEntity.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaEntity.java @@ -345,15 +345,33 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn return getTable().getDbTable(); } + private static final org.eclipse.jpt.db.Table[] EMPTY_DB_TABLE_ARRAY = new org.eclipse.jpt.db.Table[0]; + @Override public org.eclipse.jpt.db.Table getDbTable(String tableName) { - for (Iterator<Table> stream = this.associatedTablesIncludingInherited(); stream.hasNext();) { - org.eclipse.jpt.db.Table dbTable = stream.next().getDbTable(); - if (dbTable != null && dbTable.matchesShortJavaClassName(tableName)) { - return dbTable; + // the JPA platform searches database objects for us + return this.getDataSource().getDatabaseObjectNamed( + CollectionTools.array(this.associatedDbTablesIncludingInherited(), EMPTY_DB_TABLE_ARRAY), + tableName + ); + } + + private Iterator<org.eclipse.jpt.db.Table> associatedDbTablesIncludingInherited() { + return new FilteringIterator<org.eclipse.jpt.db.Table, org.eclipse.jpt.db.Table>(this.associatedDbTablesIncludingInherited_()) { + @Override + protected boolean accept(org.eclipse.jpt.db.Table t) { + return t != null; } - } - return null; + }; + } + + private Iterator<org.eclipse.jpt.db.Table> associatedDbTablesIncludingInherited_() { + return new TransformationIterator<Table, org.eclipse.jpt.db.Table>(this.associatedTablesIncludingInherited()) { + @Override + protected org.eclipse.jpt.db.Table transform(Table t) { + return t.getDbTable(); + } + }; } @Override @@ -578,7 +596,7 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn public JavaTableGenerator addTableGenerator() { if (getTableGenerator() != null) { - throw new IllegalStateException("tableGenerator already exists"); + throw new IllegalStateException("tableGenerator already exists"); //$NON-NLS-1$ } this.tableGenerator = getJpaFactory().buildJavaTableGenerator(this); TableGeneratorAnnotation tableGeneratorResource = (TableGeneratorAnnotation) this.javaResourcePersistentType.addAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); @@ -589,7 +607,7 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn public void removeTableGenerator() { if (getTableGenerator() == null) { - throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); + throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); //$NON-NLS-1$ } JavaTableGenerator oldTableGenerator = this.tableGenerator; this.tableGenerator = null; @@ -609,7 +627,7 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn public JavaSequenceGenerator addSequenceGenerator() { if (getSequenceGenerator() != null) { - throw new IllegalStateException("sequenceGenerator already exists"); + throw new IllegalStateException("sequenceGenerator already exists"); //$NON-NLS-1$ } this.sequenceGenerator = getJpaFactory().buildJavaSequenceGenerator(this); SequenceGeneratorAnnotation sequenceGeneratorResource = (SequenceGeneratorAnnotation) this.javaResourcePersistentType.addAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); @@ -620,7 +638,7 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn public void removeSequenceGenerator() { if (getSequenceGenerator() == null) { - throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); + throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); //$NON-NLS-1$ } JavaSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; this.sequenceGenerator = null; @@ -1330,8 +1348,8 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn this.updatePersistenceUnitGeneratorsAndQueries(); } - protected String specifiedName(EntityAnnotation entityResource) { - return entityResource.getName(); + protected String specifiedName(EntityAnnotation entityAnnotation) { + return entityAnnotation.getName(); } protected String defaultName(JavaResourcePersistentType persistentTypeResource) { @@ -1438,9 +1456,9 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn } protected JavaTableGenerator buildTableGenerator(TableGeneratorAnnotation tableGeneratorResource) { - JavaTableGenerator tableGenerator = getJpaFactory().buildJavaTableGenerator(this); - tableGenerator.initializeFromResource(tableGeneratorResource); - return tableGenerator; + JavaTableGenerator generator = getJpaFactory().buildJavaTableGenerator(this); + generator.initializeFromResource(tableGeneratorResource); + return generator; } protected TableGeneratorAnnotation tableGenerator(JavaResourcePersistentType persistentTypeResource) { @@ -1465,9 +1483,9 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn } protected JavaSequenceGenerator buildSequenceGenerator(SequenceGeneratorAnnotation sequenceGeneratorResource) { - JavaSequenceGenerator sequenceGenerator = getJpaFactory().buildJavaSequenceGenerator(this); - sequenceGenerator.initializeFromResource(sequenceGeneratorResource); - return sequenceGenerator; + JavaSequenceGenerator generator = getJpaFactory().buildJavaSequenceGenerator(this); + generator.initializeFromResource(sequenceGeneratorResource); + return generator; } protected SequenceGeneratorAnnotation sequenceGenerator(JavaResourcePersistentType persistentTypeResource) { @@ -1619,11 +1637,11 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn } protected void updateNamedQueries(JavaResourcePersistentType resourcePersistentType) { - ListIterator<JavaNamedQuery> namedQueries = namedQueries(); + ListIterator<JavaNamedQuery> queries = namedQueries(); ListIterator<JavaResourceNode> resourceNamedQueries = resourcePersistentType.annotations(NamedQueryAnnotation.ANNOTATION_NAME, NamedQueriesAnnotation.ANNOTATION_NAME); - while (namedQueries.hasNext()) { - JavaNamedQuery namedQuery = namedQueries.next(); + while (queries.hasNext()) { + JavaNamedQuery namedQuery = queries.next(); if (resourceNamedQueries.hasNext()) { namedQuery.update((NamedQueryAnnotation) resourceNamedQueries.next()); } @@ -1638,11 +1656,11 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn } protected void updateNamedNativeQueries(JavaResourcePersistentType resourcePersistentType) { - ListIterator<JavaNamedNativeQuery> namedNativeQueries = namedNativeQueries(); + ListIterator<JavaNamedNativeQuery> queries = namedNativeQueries(); ListIterator<JavaResourceNode> resourceNamedNativeQueries = resourcePersistentType.annotations(NamedNativeQueryAnnotation.ANNOTATION_NAME, NamedNativeQueriesAnnotation.ANNOTATION_NAME); - while (namedNativeQueries.hasNext()) { - JavaNamedNativeQuery namedQuery = namedNativeQueries.next(); + while (queries.hasNext()) { + JavaNamedNativeQuery namedQuery = queries.next(); if (resourceNamedNativeQueries.hasNext()) { namedQuery.update((NamedNativeQueryAnnotation) resourceNamedNativeQueries.next()); } @@ -1670,9 +1688,9 @@ public class GenericJavaEntity extends AbstractJavaTypeMapping implements JavaEn } protected void updateIdClass(JavaResourcePersistentType resourcePersistentType) { - IdClassAnnotation idClass = (IdClassAnnotation) resourcePersistentType.getAnnotation(IdClassAnnotation.ANNOTATION_NAME); - if (idClass != null) { - setIdClass_(idClass.getValue()); + IdClassAnnotation annotation = (IdClassAnnotation) resourcePersistentType.getAnnotation(IdClassAnnotation.ANNOTATION_NAME); + if (annotation != null) { + setIdClass_(annotation.getValue()); } else { setIdClass_(null); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinColumn.java index 35d5029cef..0287b866b5 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinColumn.java @@ -91,7 +91,7 @@ public class GenericJavaJoinColumn extends AbstractJavaBaseColumn<JoinColumnAnno public Column getDbReferencedColumn() { Table table = this.getDbReferencedColumnTable(); - return (table == null) ? null : table.columnNamed(this.getReferencedColumnName()); + return (table == null) ? null : table.getColumnNamed(this.getReferencedColumnName()); } @Override diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTable.java index b759f0e36f..83c80aa6d2 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTable.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaJoinTable.java @@ -712,10 +712,7 @@ public class GenericJavaJoinTable extends AbstractJavaTable implements JavaJoinT @Override public org.eclipse.jpt.db.Table getDbTable(String tableName) { org.eclipse.jpt.db.Table dbTable = super.getDbTable(tableName); - if (dbTable != null) { - return dbTable; - } - return getTypeMapping().getDbTable(tableName); + return (dbTable != null) ? dbTable : this.getTypeMapping().getDbTable(tableName); } public org.eclipse.jpt.db.Table getDbReferencedColumnTable() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPersistentAttribute.java index 7c0cfcd257..5ea86ea411 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPersistentAttribute.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPersistentAttribute.java @@ -250,7 +250,7 @@ public class GenericJavaPersistentAttribute extends AbstractJavaJpaContextNode } protected void updateDefaultMapping(JavaResourcePersistentAttribute jrpa) { - String defaultMappingKey = getJpaPlatform().defaultJavaAttributeMappingKey(this); + String defaultMappingKey = getJpaPlatform().getDefaultJavaAttributeMappingKey(this); if (getDefaultMapping().getKey() != defaultMappingKey) { JavaAttributeMapping oldDefaultMapping = this.defaultMapping; this.defaultMapping = getJpaPlatform().buildDefaultJavaAttributeMapping(this); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPrimaryKeyJoinColumn.java index 42c1f756ad..29b4ffbab3 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPrimaryKeyJoinColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaPrimaryKeyJoinColumn.java @@ -100,7 +100,7 @@ public class GenericJavaPrimaryKeyJoinColumn extends AbstractJavaNamedColumn<Pri public Column getDbReferencedColumn() { Table table = this.getDbReferencedColumnTable(); - return (table == null) ? null : table.columnNamed(this.getReferencedColumnName()); + return (table == null) ? null : table.getColumnNamed(this.getReferencedColumnName()); } public Table getDbReferencedColumnTable() { @@ -166,4 +166,11 @@ public class GenericJavaPrimaryKeyJoinColumn extends AbstractJavaNamedColumn<Pri return defaultName(); } + @Override + public void toString(StringBuilder sb) { + super.toString(sb); + sb.append("=>"); + sb.append(this.getReferencedColumnName()); + } + } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaTableGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaTableGenerator.java index 63d687771d..f30ab32c96 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaTableGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/java/GenericJavaTableGenerator.java @@ -388,11 +388,11 @@ public class GenericJavaTableGenerator extends AbstractJavaGenerator public Table getDbTable() { Schema schema = this.getDbSchema(); - return (schema == null) ? null : schema.tableNamed(this.getTable()); + return (schema == null) ? null : schema.getTableNamed(this.getTable()); } public Schema getDbSchema() { - return this.getDatabase().schemaNamed(this.getSchema()); + return this.getDataSource().getSchemaNamed(this.getSchema()); } } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmNamedColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmNamedColumn.java index f07f27ee7c..b54a586675 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmNamedColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmNamedColumn.java @@ -126,7 +126,7 @@ public abstract class AbstractOrmNamedColumn<T extends XmlNamedColumn> extends public Column getDbColumn() { Table table = this.getDbTable(); - return (table == null) ? null : table.columnNamed(getName()); + return (table == null) ? null : table.getColumnNamed(getName()); } public Table getDbTable() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java index 941670e156..7406f6f2c4 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmRelationshipMapping.java @@ -137,10 +137,6 @@ public abstract class AbstractOrmRelationshipMapping<T extends XmlRelationshipMa return null; } - public boolean targetEntityIsValid(String targetEntity) { - return MappingTools.targetEntityIsValid(targetEntity); - } - @Override public void initialize(T relationshipMapping) { super.initialize(relationshipMapping); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java index c2cc70db36..46d2cdfb7c 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/AbstractOrmTable.java @@ -260,11 +260,11 @@ public abstract class AbstractOrmTable extends AbstractOrmJpaContextNode impleme public org.eclipse.jpt.db.Table getDbTable() { Schema schema = this.getDbSchema(); - return (schema == null) ? null : schema.tableNamed(getName()); + return (schema == null) ? null : schema.getTableNamed(getName()); } public Schema getDbSchema() { - return getConnectionProfile().getDatabase().schemaNamed(getSchema()); + return this.getDataSource().getSchemaNamed(getSchema()); } public boolean hasResolvedSchema() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmEntity.java index 3637306b43..cfa37c050c 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmEntity.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmEntity.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; + import org.eclipse.jpt.core.MappingKeys; import org.eclipse.jpt.core.context.AssociationOverride; import org.eclipse.jpt.core.context.AttributeOverride; @@ -37,7 +38,6 @@ import org.eclipse.jpt.core.context.Table; import org.eclipse.jpt.core.context.TypeMapping; import org.eclipse.jpt.core.context.java.JavaAttributeOverride; import org.eclipse.jpt.core.context.java.JavaEntity; -import org.eclipse.jpt.core.context.java.JavaPersistentType; import org.eclipse.jpt.core.context.java.JavaPrimaryKeyJoinColumn; import org.eclipse.jpt.core.context.java.JavaSecondaryTable; import org.eclipse.jpt.core.context.orm.OrmAssociationOverride; @@ -192,15 +192,33 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen return getTable().getDbTable(); } + private static final org.eclipse.jpt.db.Table[] EMPTY_DB_TABLE_ARRAY = new org.eclipse.jpt.db.Table[0]; + @Override public org.eclipse.jpt.db.Table getDbTable(String tableName) { - for (Iterator<Table> stream = this.associatedTablesIncludingInherited(); stream.hasNext();) { - org.eclipse.jpt.db.Table dbTable = stream.next().getDbTable(); - if (dbTable != null && dbTable.matchesShortJavaClassName(tableName)) { - return dbTable; + // the JPA platform searches database objects for us + return this.getDataSource().getDatabaseObjectNamed( + CollectionTools.array(this.associatedDbTablesIncludingInherited(), EMPTY_DB_TABLE_ARRAY), + tableName + ); + } + + private Iterator<org.eclipse.jpt.db.Table> associatedDbTablesIncludingInherited() { + return new FilteringIterator<org.eclipse.jpt.db.Table, org.eclipse.jpt.db.Table>(this.associatedDbTablesIncludingInherited_()) { + @Override + protected boolean accept(org.eclipse.jpt.db.Table t) { + return t != null; } - } - return null; + }; + } + + private Iterator<org.eclipse.jpt.db.Table> associatedDbTablesIncludingInherited_() { + return new TransformationIterator<Table, org.eclipse.jpt.db.Table>(this.associatedTablesIncludingInherited()) { + @Override + protected org.eclipse.jpt.db.Table transform(Table t) { + return t.getDbTable(); + } + }; } @Override @@ -209,9 +227,8 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } public JavaEntity getJavaEntity() { - JavaPersistentType javaPersistentType = getJavaPersistentType(); - if (javaPersistentType != null && javaPersistentType.getMappingKey() == MappingKeys.ENTITY_TYPE_MAPPING_KEY) { - return (JavaEntity) javaPersistentType.getMapping(); + if (this.javaPersistentType != null && this.javaPersistentType.getMappingKey() == MappingKeys.ENTITY_TYPE_MAPPING_KEY) { + return (JavaEntity) this.javaPersistentType.getMapping(); } return null; } @@ -285,7 +302,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public OrmSecondaryTable addSpecifiedSecondaryTable(int index) { if (!secondaryTablesDefinedInXml()) { - throw new IllegalStateException("Virtual secondary tables exist, must first call setSecondaryTablesDefinedInXml(true)"); + throw new IllegalStateException("Virtual secondary tables exist, must first call setSecondaryTablesDefinedInXml(true)"); //$NON-NLS-1$ } XmlSecondaryTable secondaryTableResource = OrmFactory.eINSTANCE.createXmlSecondaryTableImpl(); OrmSecondaryTable secondaryTable = buildSecondaryTable(secondaryTableResource); @@ -369,8 +386,8 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen */ protected void specifySecondaryTablesInXml() { if (virtualSecondaryTablesSize() != 0) { - List<OrmSecondaryTable> virtualSecondaryTables = CollectionTools.list(this.virtualSecondaryTables()); - List<OrmSecondaryTable> virtualSecondaryTable2 = CollectionTools.list(this.virtualSecondaryTables()); + List<OrmSecondaryTable> virtualSecondaryTables1 = CollectionTools.list(this.virtualSecondaryTables()); + List<OrmSecondaryTable> virtualSecondaryTables2 = CollectionTools.list(this.virtualSecondaryTables()); //remove all the virtual secondary tables without firing change notification. for (OrmSecondaryTable virtualSecondaryTable : CollectionTools.iterable(virtualSecondaryTables())) { this.virtualSecondaryTables.remove(virtualSecondaryTable); @@ -378,7 +395,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen //add specified secondary tables for each virtual secondary table. If the virtual secondary tables //are not removed first, they will be removed as a side effect of adding the first specified secondary table. //This screws up the change notification to the UI, since that change notification is in a different thread - for (OrmSecondaryTable virtualSecondaryTable : virtualSecondaryTable2) { + for (OrmSecondaryTable virtualSecondaryTable : virtualSecondaryTables2) { XmlSecondaryTable secondaryTableResource = OrmFactory.eINSTANCE.createXmlSecondaryTableImpl(); OrmSecondaryTable specifiedSecondaryTable = buildSecondaryTable(secondaryTableResource); this.specifiedSecondaryTables.add(specifiedSecondaryTable); @@ -386,14 +403,14 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen specifiedSecondaryTable.initializeFrom(virtualSecondaryTable); } //fire change notification at the end - fireItemsRemoved(OrmEntity.VIRTUAL_SECONDARY_TABLES_LIST, 0, virtualSecondaryTables); + fireItemsRemoved(OrmEntity.VIRTUAL_SECONDARY_TABLES_LIST, 0, virtualSecondaryTables1); fireItemsAdded(Entity.SPECIFIED_SECONDARY_TABLES_LIST, 0, this.specifiedSecondaryTables); } } protected void removeSecondaryTablesFromXml() { if (specifiedSecondaryTablesSize() != 0) { - List<OrmSecondaryTable> specifiedSecondaryTables = CollectionTools.list(this.specifiedSecondaryTables()); + List<OrmSecondaryTable> specifiedSecondaryTablesCopy = CollectionTools.list(this.specifiedSecondaryTables()); for (OrmSecondaryTable specifiedSecondaryTable : CollectionTools.iterable(specifiedSecondaryTables())) { int index = this.specifiedSecondaryTables.indexOf(specifiedSecondaryTable); this.specifiedSecondaryTables.remove(specifiedSecondaryTable); @@ -402,7 +419,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } getTypeMappingResource().getSecondaryTables().remove(index); } - fireItemsRemoved(Entity.SPECIFIED_SECONDARY_TABLES_LIST, 0, specifiedSecondaryTables); + fireItemsRemoved(Entity.SPECIFIED_SECONDARY_TABLES_LIST, 0, specifiedSecondaryTablesCopy); if (this.virtualSecondaryTables.size() != 0) { fireItemsAdded(OrmEntity.VIRTUAL_SECONDARY_TABLES_LIST, 0, this.virtualSecondaryTables); } @@ -516,7 +533,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public OrmSequenceGenerator addSequenceGenerator() { if (getSequenceGenerator() != null) { - throw new IllegalStateException("sequenceGenerator already exists"); + throw new IllegalStateException("sequenceGenerator already exists"); //$NON-NLS-1$ } this.sequenceGenerator = getJpaFactory().buildOrmSequenceGenerator(this); getTypeMappingResource().setSequenceGenerator(OrmFactory.eINSTANCE.createXmlSequenceGeneratorImpl()); @@ -526,7 +543,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public void removeSequenceGenerator() { if (getSequenceGenerator() == null) { - throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); + throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); //$NON-NLS-1$ } OrmSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; this.sequenceGenerator = null; @@ -546,7 +563,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public OrmTableGenerator addTableGenerator() { if (getTableGenerator() != null) { - throw new IllegalStateException("tableGenerator already exists"); + throw new IllegalStateException("tableGenerator already exists"); //$NON-NLS-1$ } this.tableGenerator = getJpaFactory().buildOrmTableGenerator(this); getTypeMappingResource().setTableGenerator(OrmFactory.eINSTANCE.createXmlTableGeneratorImpl()); @@ -556,7 +573,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public void removeTableGenerator() { if (getTableGenerator() == null) { - throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); + throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); //$NON-NLS-1$ } OrmTableGenerator oldTableGenerator = this.tableGenerator; this.tableGenerator = null; @@ -625,7 +642,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } public OrmPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() { - throw new UnsupportedOperationException("use defaultPrimaryKeyJoinColumns() instead"); + throw new UnsupportedOperationException("use defaultPrimaryKeyJoinColumns() instead"); //$NON-NLS-1$ } protected void addDefaultPrimaryKeyJoinColumn(OrmPrimaryKeyJoinColumn defaultPkJoinColumn) { @@ -1032,9 +1049,9 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen public Entity getParentEntity() { for (Iterator<PersistentType> i = getPersistentType().inheritanceHierarchy(); i.hasNext();) { - TypeMapping typeMapping = i.next().getMapping(); - if (typeMapping != this && typeMapping instanceof Entity) { - return (Entity) typeMapping; + TypeMapping tm = i.next().getMapping(); + if (tm != this && tm instanceof Entity) { + return (Entity) tm; } } return this; @@ -1270,9 +1287,9 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } protected OrmTableGenerator buildTableGenerator(XmlTableGenerator tableGeneratorResource) { - OrmTableGenerator tableGenerator = getJpaFactory().buildOrmTableGenerator(this); - tableGenerator.initialize(tableGeneratorResource); - return tableGenerator; + OrmTableGenerator generator = getJpaFactory().buildOrmTableGenerator(this); + generator.initialize(tableGeneratorResource); + return generator; } protected void initializeSequenceGenerator(XmlEntity entity) { @@ -1282,9 +1299,9 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } protected OrmSequenceGenerator buildSequenceGenerator(XmlSequenceGenerator xmlSequenceGenerator) { - OrmSequenceGenerator sequenceGenerator = getJpaFactory().buildOrmSequenceGenerator(this); - sequenceGenerator.initialize(xmlSequenceGenerator); - return sequenceGenerator; + OrmSequenceGenerator generator = getJpaFactory().buildOrmSequenceGenerator(this); + generator.initialize(xmlSequenceGenerator); + return generator; } protected void initializeSpecifiedPrimaryKeyJoinColumns(XmlEntity entity) { @@ -1598,7 +1615,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen protected void updateVirtualAttributeOverrides() { Iterator<PersistentAttribute> overridableAttributes = allOverridableAttributes(); - ListIterator<OrmAttributeOverride> virtualAttributeOverrides = virtualAttributeOverrides(); + ListIterator<OrmAttributeOverride> virtualAttributeOverridesCopy = virtualAttributeOverrides(); for (PersistentAttribute persistentAttribute : CollectionTools.iterable(overridableAttributes)) { OrmAttributeOverride ormAttributeOverride = getAttributeOverrideNamed(persistentAttribute.getName()); @@ -1610,8 +1627,8 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen javaAttributeOverride = getJavaEntity().getAttributeOverrideNamed(persistentAttribute.getName()); } if (ormAttributeOverride != null) { - if (virtualAttributeOverrides.hasNext()) { - OrmAttributeOverride virtualAttributeOverride = virtualAttributeOverrides.next(); + if (virtualAttributeOverridesCopy.hasNext()) { + OrmAttributeOverride virtualAttributeOverride = virtualAttributeOverridesCopy.next(); virtualAttributeOverride.update(buildVirtualXmlAttributeOverride(persistentAttribute, javaAttributeOverride)); } else { @@ -1622,7 +1639,7 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen addVirtualAttributeOverride(buildVirtualAttributeOverride(persistentAttribute, javaAttributeOverride)); } } - for (OrmAttributeOverride virtualAttributeOverride : CollectionTools.iterable(virtualAttributeOverrides)) { + for (OrmAttributeOverride virtualAttributeOverride : CollectionTools.iterable(virtualAttributeOverridesCopy)) { removeVirtualAttributeOverride(virtualAttributeOverride); } } @@ -1663,11 +1680,11 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } protected void updateNamedQueries(XmlEntity entity) { - ListIterator<OrmNamedQuery> namedQueries = namedQueries(); + ListIterator<OrmNamedQuery> queries = namedQueries(); ListIterator<XmlNamedQuery> resourceNamedQueries = new CloneListIterator<XmlNamedQuery>(entity.getNamedQueries());//prevent ConcurrentModificiationException - while (namedQueries.hasNext()) { - OrmNamedQuery namedQuery = namedQueries.next(); + while (queries.hasNext()) { + OrmNamedQuery namedQuery = queries.next(); if (resourceNamedQueries.hasNext()) { namedQuery.update(resourceNamedQueries.next()); } @@ -1688,11 +1705,11 @@ public class GenericOrmEntity extends AbstractOrmTypeMapping<XmlEntity> implemen } protected void updateNamedNativeQueries(XmlEntity entity) { - ListIterator<OrmNamedNativeQuery> namedNativeQueries = namedNativeQueries(); + ListIterator<OrmNamedNativeQuery> queries = namedNativeQueries(); ListIterator<XmlNamedNativeQuery> resourceNamedNativeQueries = new CloneListIterator<XmlNamedNativeQuery>(entity.getNamedNativeQueries());//prevent ConcurrentModificiationException - while (namedNativeQueries.hasNext()) { - OrmNamedNativeQuery namedQuery = namedNativeQueries.next(); + while (queries.hasNext()) { + OrmNamedNativeQuery namedQuery = queries.next(); if (resourceNamedNativeQueries.hasNext()) { namedQuery.update(resourceNamedNativeQueries.next()); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinColumn.java index 6a8c21895d..03f210e9f5 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinColumn.java @@ -88,7 +88,7 @@ public class GenericOrmJoinColumn extends AbstractOrmBaseColumn<XmlJoinColumn> i public Column getDbReferencedColumn() { Table table = dbReferencedColumnTable(); - return (table == null) ? null : table.columnNamed(getReferencedColumnName()); + return (table == null) ? null : table.getColumnNamed(getReferencedColumnName()); } public boolean isReferencedColumnResolved() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTable.java index 03e0a0a091..74609dd1c3 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTable.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmJoinTable.java @@ -671,10 +671,7 @@ public class GenericOrmJoinTable extends AbstractOrmTable implements OrmJoinTabl @Override public org.eclipse.jpt.db.Table getDbTable(String tableName) { org.eclipse.jpt.db.Table dbTable = super.getDbTable(tableName); - if (dbTable != null) { - return dbTable; - } - return getTypeMapping().getDbTable(tableName); + return (dbTable != null) ? dbTable : getTypeMapping().getDbTable(tableName); } public org.eclipse.jpt.db.Table getDbReferencedColumnTable() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmPrimaryKeyJoinColumn.java index 4710e4b714..8a664ad8e3 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmPrimaryKeyJoinColumn.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmPrimaryKeyJoinColumn.java @@ -91,7 +91,7 @@ public class GenericOrmPrimaryKeyJoinColumn extends AbstractOrmNamedColumn<XmlPr public Column getDbReferencedColumn() { Table table = this.dbReferencedColumnTable(); - return (table == null) ? null : table.columnNamed(this.getReferencedColumnName()); + return (table == null) ? null : table.getColumnNamed(this.getReferencedColumnName()); } public Table dbReferencedColumnTable() { diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmTableGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmTableGenerator.java index 57e8df7551..0d8dd025bd 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmTableGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericOrmTableGenerator.java @@ -299,11 +299,11 @@ public class GenericOrmTableGenerator extends AbstractOrmGenerator<XmlTableGener public Table getDbTable() { Schema schema = this.getDbSchema(); - return (schema == null) ? null : schema.tableNamed(this.getTable()); + return (schema == null) ? null : schema.getTableNamed(this.getTable()); } public Schema getDbSchema() { - return this.getDatabase().schemaNamed(this.getSchema()); + return this.getDataSource().getSchemaNamed(this.getSchema()); } // ********** orm resource model -> context model ********** diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericPersistenceUnitDefaults.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericPersistenceUnitDefaults.java index 847e081d33..9f10a4dad0 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericPersistenceUnitDefaults.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/orm/GenericPersistenceUnitDefaults.java @@ -243,7 +243,7 @@ public class GenericPersistenceUnitDefaults extends AbstractOrmJpaContextNode } protected String projectDefaultCatalogName() { - Catalog catalog = getJpaProject().getConnectionProfile().getDefaultCatalog(); + Catalog catalog = this.getJpaProject().getDataSource().getDefaultCatalog(); return (catalog == null) ? null : catalog.getName(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericPersistenceUnit.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericPersistenceUnit.java index 395bc9c04f..6a4b38c013 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericPersistenceUnit.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/context/persistence/GenericPersistenceUnit.java @@ -1054,7 +1054,7 @@ public class GenericPersistenceUnit extends AbstractPersistenceJpaContextNode } protected String projectDefaultCatalogName() { - Catalog catalog = getJpaProject().getConnectionProfile().getDefaultCatalog(); + Catalog catalog = this.getJpaProject().getDataSource().getDefaultCatalog(); return (catalog == null) ? null : catalog.getName(); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/facet/JpaFacetDataModelProvider.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/facet/JpaFacetDataModelProvider.java index 1861925bf2..e079866c9c 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/facet/JpaFacetDataModelProvider.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/facet/JpaFacetDataModelProvider.java @@ -9,9 +9,11 @@ ******************************************************************************/ package org.eclipse.jpt.core.internal.facet; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; + import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.JavaCore; @@ -19,11 +21,14 @@ import org.eclipse.jpt.core.JptCorePlugin; import org.eclipse.jpt.core.internal.JptCoreMessages; import org.eclipse.jpt.core.internal.platform.JpaPlatformRegistry; import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.ConnectionProfileFactory; +import org.eclipse.jpt.db.Database; import org.eclipse.jpt.db.JptDbPlugin; import org.eclipse.jpt.db.Schema; import org.eclipse.jpt.utility.internal.CollectionTools; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; import org.eclipse.wst.common.componentcore.datamodel.FacetInstallDataModelProvider; import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants; @@ -111,7 +116,7 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider return null; } if (propertyName.equals(CONNECTION_ACTIVE)) { - return connectionIsActive(); + return Boolean.valueOf(connectionIsActive()); } if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)) { return Boolean.FALSE; @@ -126,7 +131,7 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider return Boolean.valueOf(this.runtimeSupportsEjb30(this.runtime())); } if (propertyName.equals(USE_USER_JPA_LIBRARY)) { - return ! getBooleanProperty(USE_SERVER_JPA_IMPLEMENTATION); + return Boolean.valueOf( ! getBooleanProperty(USE_SERVER_JPA_IMPLEMENTATION)); } if (propertyName.equals(JPA_LIBRARY)) { return JptCorePlugin.getDefaultJpaLibrary(); @@ -135,7 +140,7 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider return Boolean.valueOf(this.runtimeSupportsEjb30(this.runtime())); } if (propertyName.equals(LIST_ANNOTATED_CLASSES)) { - return ! getBooleanProperty(DISCOVER_ANNOTATED_CLASSES); + return Boolean.valueOf( ! getBooleanProperty(DISCOVER_ANNOTATED_CLASSES)); } if (propertyName.equals(CREATE_ORM_XML)) { return Boolean.TRUE; @@ -169,26 +174,28 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider } if (propertyName.equals(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA)) { this.model.notifyPropertyChange(USER_OVERRIDE_DEFAULT_SCHEMA, IDataModel.ENABLE_CHG); - if (! (Boolean) propertyValue) { + if (! ((Boolean) propertyValue).booleanValue()) { this.model.setProperty(USER_OVERRIDE_DEFAULT_SCHEMA, null); } } if (propertyName.equals(USE_SERVER_JPA_IMPLEMENTATION)) { - this.model.setBooleanProperty(USE_USER_JPA_LIBRARY, ! (Boolean) propertyValue); + this.model.setBooleanProperty(USE_USER_JPA_LIBRARY, ! ((Boolean) propertyValue).booleanValue()); } if (propertyName.equals(USE_USER_JPA_LIBRARY)) { - this.model.setBooleanProperty(USE_SERVER_JPA_IMPLEMENTATION, ! (Boolean) propertyValue); + this.model.setBooleanProperty(USE_SERVER_JPA_IMPLEMENTATION, ! ((Boolean) propertyValue).booleanValue()); this.model.notifyPropertyChange(JPA_LIBRARY, IDataModel.ENABLE_CHG); } if (propertyName.equals(DISCOVER_ANNOTATED_CLASSES)) { - this.model.setBooleanProperty(LIST_ANNOTATED_CLASSES, ! (Boolean) propertyValue); + this.model.setBooleanProperty(LIST_ANNOTATED_CLASSES, ! ((Boolean) propertyValue).booleanValue()); } if (propertyName.equals(LIST_ANNOTATED_CLASSES)) { - this.model.setBooleanProperty(DISCOVER_ANNOTATED_CLASSES, ! (Boolean) propertyValue); + this.model.setBooleanProperty(DISCOVER_ANNOTATED_CLASSES, ! ((Boolean) propertyValue).booleanValue()); } return ok; } + private static final DataModelPropertyDescriptor[] EMPTY_DMPD_ARRAY = new DataModelPropertyDescriptor[0]; + @Override public DataModelPropertyDescriptor[] getValidPropertyDescriptors(String propertyName) { if (propertyName.equals(PLATFORM_ID)) { @@ -200,35 +207,35 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider return platformIdPropertyDescriptor(platformId); } }, - new DataModelPropertyDescriptor[0]); + EMPTY_DMPD_ARRAY); } if (propertyName.equals(CONNECTION)) { return CollectionTools.array( new TransformationIterator<String, DataModelPropertyDescriptor>( new CompositeIterator<String>( null, - JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNames())) { + this.getConnectionProfileFactory().connectionProfileNames())) { @Override protected DataModelPropertyDescriptor transform(String next) { return connectionPropertyDescriptor(next); } }, - new DataModelPropertyDescriptor[0]); + EMPTY_DMPD_ARRAY); } if (propertyName.equals(USER_OVERRIDE_DEFAULT_SCHEMA)) { return CollectionTools.array( - new TransformationIterator<String, DataModelPropertyDescriptor>(schemas()) { + new TransformationIterator<String, DataModelPropertyDescriptor>(schemaNames()) { @Override protected DataModelPropertyDescriptor transform(String next) { return new DataModelPropertyDescriptor(next); } }, - new DataModelPropertyDescriptor[0]); + EMPTY_DMPD_ARRAY); } if (propertyName.equals(JPA_LIBRARY)) { String[] libraries = CollectionTools.sort(JavaCore.getUserLibraryNames()); DataModelPropertyDescriptor[] descriptors = new DataModelPropertyDescriptor[libraries.length + 1]; - descriptors[0] = new DataModelPropertyDescriptor("", RUNTIME_NONE); + descriptors[0] = new DataModelPropertyDescriptor("", RUNTIME_NONE); //$NON-NLS-1$ int i = 1; for (String library : libraries) { @@ -251,18 +258,16 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider return super.getPropertyDescriptor(propertyName); } - private DataModelPropertyDescriptor platformIdPropertyDescriptor(String platformId) { + DataModelPropertyDescriptor platformIdPropertyDescriptor(String platformId) { return new DataModelPropertyDescriptor( platformId, JpaPlatformRegistry.instance().getJpaPlatformLabel(platformId)); } - private DataModelPropertyDescriptor connectionPropertyDescriptor(String connection) { - if (StringTools.stringIsEmpty(connection)) { - return new DataModelPropertyDescriptor(null, JptCoreMessages.NONE); - } - else { - return new DataModelPropertyDescriptor(connection); - } + DataModelPropertyDescriptor connectionPropertyDescriptor(String connection) { + return StringTools.stringIsEmpty(connection) ? + new DataModelPropertyDescriptor(null, JptCoreMessages.NONE) + : + new DataModelPropertyDescriptor(connection); } @Override @@ -291,41 +296,69 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider } private boolean runtimeSupportsEjb30(IRuntime runtime) { - IProjectFacetVersion ejb30 = ProjectFacetsManager.getProjectFacet(EJB_FACET_ID).getVersion("3.0"); + IProjectFacetVersion ejb30 = ProjectFacetsManager.getProjectFacet(EJB_FACET_ID).getVersion("3.0"); //$NON-NLS-1$ return (runtime == null) ? false : runtime.supports(ejb30); } - - private ConnectionProfile getConnection() { - String connectionName = getStringProperty(CONNECTION); - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(connectionName); + + private String getConnectionName() { + return this.getStringProperty(CONNECTION); } + private ConnectionProfile getConnectionProfile() { + return this.buildConnectionProfile(this.getConnectionName()); + } + + private ConnectionProfileFactory getConnectionProfileFactory() { + // we don't have a JPA project yet, so go to the db plug-in directly to get the factory + return JptDbPlugin.instance().getConnectionProfileFactory(); + } + + private ConnectionProfile buildConnectionProfile(String name) { + return this.getConnectionProfileFactory().buildConnectionProfile(name); + } + private boolean connectionIsActive() { - return getConnection().isActive(); + return this.connectionIsActive(this.getConnectionName()); + } + + private boolean connectionIsActive(String connectionName) { + ConnectionProfile cp = this.buildConnectionProfile(connectionName); + return (cp != null) && cp.isActive(); } private String getDefaultSchemaName() { - Schema defaultSchema = getConnection().getDefaultSchema(); - return (defaultSchema == null) ? null : defaultSchema.getName(); + ConnectionProfile cp = this.getConnectionProfile(); + if (cp == null) { + return null; + } + Database db = cp.getDatabase(); + if (db == null) { + return null; + } + Schema schema = db.getDefaultSchema(); + return (schema == null) ? null : schema.getName(); } - - private Iterator<String> schemas() { + + private List<String> buildSortedSchemaNames() { + ConnectionProfile cp = this.getConnectionProfile(); + if (cp == null) { + return Collections.emptyList(); + } + Database db = cp.getDatabase(); + if (db == null) { + return Collections.emptyList(); + } + return CollectionTools.sort(CollectionTools.list(db.schemaNames())); + } + + private Iterator<String> schemaNames() { String setValue = getStringProperty(USER_OVERRIDE_DEFAULT_SCHEMA); + List<String> schemaNames = this.buildSortedSchemaNames(); - List<String> schemas = CollectionTools.sort(CollectionTools.list( - new TransformationIterator<Schema, String>(getConnection().getDatabase().schemata()) { - @Override - protected String transform(Schema next) { - return next.getName(); - } - })); - - if (! StringTools.stringIsEmpty(setValue) && ! schemas.contains(setValue)) { - return new CompositeIterator<String>(setValue, schemas.iterator()); - } - else { - return schemas.iterator(); + if (StringTools.stringIsEmpty(setValue) || schemaNames.contains(setValue)) { + return schemaNames.iterator(); } + return new CompositeIterator<String>(setValue, schemaNames.iterator()); } @@ -339,10 +372,14 @@ public class JpaFacetDataModelProvider extends FacetInstallDataModelProvider } private IStatus validateConnectionName(String connectionName) { - if (StringTools.stringIsEmpty(connectionName)) { - return OK_STATUS; - } - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(connectionName).isActive() ? + return StringTools.stringIsEmpty(connectionName) ? + OK_STATUS + : + this.getConnectionStatus(connectionName); + } + + private IStatus getConnectionStatus(String connectionName) { + return this.connectionIsActive(connectionName) ? OK_STATUS : CONNECTION_NOT_CONNECTED_STATUS; diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java index 57f2854a82..8a4d527887 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java @@ -37,6 +37,7 @@ import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; import org.eclipse.jst.j2ee.internal.project.J2EEProjectUtilities; +import org.eclipse.osgi.util.NLS; import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelProvider; import org.eclipse.wst.common.frameworks.datamodel.DataModelPropertyDescriptor; import org.eclipse.wst.common.frameworks.datamodel.IDataModel; @@ -171,18 +172,14 @@ public class OrmFileCreationDataModelProvider extends AbstractDataModelProvider if (accessType == null) { return new DataModelPropertyDescriptor(null, JptCoreMessages.NONE); } - else { - return new DataModelPropertyDescriptor(accessType, accessType.getName()); - } + return new DataModelPropertyDescriptor(accessType, accessType.getName()); } - private DataModelPropertyDescriptor persistenceUnitPropertyDescriptor(String persistenceUnitName) { + DataModelPropertyDescriptor persistenceUnitPropertyDescriptor(String persistenceUnitName) { if (StringTools.stringIsEmpty(persistenceUnitName)) { return new DataModelPropertyDescriptor(null, JptCoreMessages.NONE); } - else { - return new DataModelPropertyDescriptor(persistenceUnitName); - } + return new DataModelPropertyDescriptor(persistenceUnitName); } @@ -223,19 +220,19 @@ public class OrmFileCreationDataModelProvider extends AbstractDataModelProvider if (sourceFolderNotInProject(sourceFolderPath)) { return new Status( IStatus.ERROR, JptCorePlugin.PLUGIN_ID, - JptCoreMessages.bind( + NLS.bind( JptCoreMessages.VALIDATE_SOURCE_FOLDER_NOT_IN_PROJECT, sourceFolderPath, projectName)); } if (getVerifiedSourceFolder() == null) { return new Status( IStatus.ERROR, JptCorePlugin.PLUGIN_ID, - JptCoreMessages.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST, sourceFolderPath)); + NLS.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST, sourceFolderPath)); } if (getVerifiedJavaSourceFolder() == null) { return new Status( IStatus.ERROR, JptCorePlugin.PLUGIN_ID, - JptCoreMessages.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER, sourceFolderPath)); + NLS.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER, sourceFolderPath)); } if (getExistingOrmFile() != null) { return new Status( @@ -253,12 +250,12 @@ public class OrmFileCreationDataModelProvider extends AbstractDataModelProvider if (StringTools.stringIsEmpty(pUnitName)) { return new Status( IStatus.ERROR, JptCorePlugin.PLUGIN_ID, - JptCoreMessages.bind(JptCoreMessages.VALIDATE_PERSISTENCE_UNIT_DOES_NOT_SPECIFIED, pUnitName)); + NLS.bind(JptCoreMessages.VALIDATE_PERSISTENCE_UNIT_DOES_NOT_SPECIFIED, pUnitName)); } if (getPersistenceUnit() == null) { return new Status( IStatus.ERROR, JptCorePlugin.PLUGIN_ID, - JptCoreMessages.bind(JptCoreMessages.VALIDATE_PERSISTENCE_UNIT_NOT_IN_PROJECT, pUnitName, projectName)); + NLS.bind(JptCoreMessages.VALIDATE_PERSISTENCE_UNIT_NOT_IN_PROJECT, pUnitName, projectName)); } } return Status.OK_STATUS; @@ -458,12 +455,7 @@ public class OrmFileCreationDataModelProvider extends AbstractDataModelProvider (jpaProject == null) ? null : jpaProject.getRootContext().getPersistenceXml(); Persistence persistence = (persistenceXml == null) ? null : persistenceXml.getPersistence(); - if (persistence == null) { - return EmptyIterator.instance(); - } - else { - return persistence.persistenceUnits(); - } + return (persistence == null) ? EmptyIterator.<PersistenceUnit>instance() : persistence.persistenceUnits(); } }); } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java new file mode 100644 index 0000000000..fc98a9926f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericEntityGeneratorDatabaseAnnotationNameBuilder.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.core.internal.platform; + +import org.eclipse.jpt.core.EntityGeneratorDatabaseAnnotationNameBuilder; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Table; + +/** + * Singleton that delegates to the db object passed in. + */ +public final class GenericEntityGeneratorDatabaseAnnotationNameBuilder + implements EntityGeneratorDatabaseAnnotationNameBuilder +{ + public static final EntityGeneratorDatabaseAnnotationNameBuilder INSTANCE + = new GenericEntityGeneratorDatabaseAnnotationNameBuilder(); + + public static EntityGeneratorDatabaseAnnotationNameBuilder instance() { + return INSTANCE; + } + + // ensure single instance + private GenericEntityGeneratorDatabaseAnnotationNameBuilder() { + super(); + } + + public String buildTableAnnotationName(String entityName, Table table) { + return table.getAnnotationIdentifier(entityName); + } + + public String buildColumnAnnotationName(String attributeName, Column column) { + return column.getAnnotationIdentifier(attributeName); + } + + public String buildJoinColumnAnnotationName(String attributeName, ForeignKey foreignKey) { + return foreignKey.getJoinColumnAnnotationIdentifier(attributeName); + } + + public String buildJoinColumnAnnotationName(Column column) { + return column.getAnnotationIdentifier(); + } + + public String buildJoinTableAnnotationName(Table table) { + return table.getAnnotationIdentifier(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java index 260f64832b..2e43677eea 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/platform/GenericJpaPlatform.java @@ -10,11 +10,12 @@ package org.eclipse.jpt.core.internal.platform; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; + import org.eclipse.core.resources.IFile; +import org.eclipse.jpt.core.EntityGeneratorDatabaseAnnotationNameBuilder; import org.eclipse.jpt.core.JpaAnnotationProvider; import org.eclipse.jpt.core.JpaFactory; import org.eclipse.jpt.core.JpaFile; @@ -43,35 +44,42 @@ import org.eclipse.jpt.core.internal.context.java.JavaOneToManyMappingProvider; import org.eclipse.jpt.core.internal.context.java.JavaOneToOneMappingProvider; import org.eclipse.jpt.core.internal.context.java.JavaTransientMappingProvider; import org.eclipse.jpt.core.internal.context.java.JavaVersionMappingProvider; +import org.eclipse.jpt.db.ConnectionProfileFactory; +import org.eclipse.jpt.db.DatabaseFinder; +import org.eclipse.jpt.db.JptDbPlugin; import org.eclipse.jpt.utility.internal.iterators.CloneIterator; import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; import org.eclipse.wst.validation.internal.provisional.core.IMessage; -public class GenericJpaPlatform implements JpaPlatform +public class GenericJpaPlatform + implements JpaPlatform { - public static String ID = "generic"; - + public static final String ID = "generic"; //$NON-NLS-1$ + private String id; - + protected JpaFactory jpaFactory; - + protected JpaAnnotationProvider annotationProvider; - - protected Collection<JavaTypeMappingProvider> javaTypeMappingProviders; - - protected Collection<JavaAttributeMappingProvider> javaAttributeMappingProviders; - + + protected List<JavaTypeMappingProvider> javaTypeMappingProviders; + + protected List<JavaAttributeMappingProvider> javaAttributeMappingProviders; + protected List<DefaultJavaAttributeMappingProvider> defaultJavaAttributeMappingProviders; - + + + /** + * zero-argument constructor + */ public GenericJpaPlatform() { super(); } - - + public String getId() { return this.id; } - + /** * ************* * * IMPORTANT * For INTERNAL use only !! @@ -82,68 +90,55 @@ public class GenericJpaPlatform implements JpaPlatform public void setId(String theId) { this.id = theId; } - - - // **************** Model construction / updating ************************** - - public JpaFactory getJpaFactory() { + + + // **************** Model construction/updating ************************** + + public synchronized JpaFactory getJpaFactory() { if (this.jpaFactory == null) { - this.jpaFactory = buildJpaFactory(); + this.jpaFactory = this.buildJpaFactory(); } return this.jpaFactory; } - + protected JpaFactory buildJpaFactory() { return new GenericJpaFactory(); } - + public JpaFile buildJpaFile(JpaProject jpaProject, IFile file) { - if (getJpaFactory().hasRelevantContent(file)) { - ResourceModel resourceModel = getJpaFactory().buildResourceModel(jpaProject, file); - return getJpaFactory().buildJpaFile(jpaProject, file, resourceModel); + if (this.getJpaFactory().hasRelevantContent(file)) { + ResourceModel resourceModel = this.getJpaFactory().buildResourceModel(jpaProject, file); + return this.getJpaFactory().buildJpaFile(jpaProject, file, resourceModel); } - return null; } - - - // **************** java annotation support ******************************** - - public JpaAnnotationProvider getAnnotationProvider() { + + + // **************** Java annotation support ******************************** + + public synchronized JpaAnnotationProvider getAnnotationProvider() { if (this.annotationProvider == null) { - this.annotationProvider = buildAnnotationProvider(); + this.annotationProvider = this.buildAnnotationProvider(); } return this.annotationProvider; } - + protected JpaAnnotationProvider buildAnnotationProvider() { return new GenericJpaAnnotationProvider(); } - - - // **************** type mapping support ******************************** - + + + // **************** Type mapping providers ******************************** + public JavaTypeMapping buildJavaTypeMappingFromMappingKey(String typeMappingKey, JavaPersistentType parent) { - return javaTypeMappingProviderFromMappingKey(typeMappingKey).buildMapping(parent, getJpaFactory()); + return this.javaTypeMappingProviderFromMappingKey(typeMappingKey).buildMapping(parent, this.getJpaFactory()); } - + public JavaTypeMapping buildJavaTypeMappingFromAnnotation(String mappingAnnotationName, JavaPersistentType parent) { - return javaTypeMappingProviderFromAnnotation(mappingAnnotationName).buildMapping(parent, getJpaFactory()); - } - - public JavaAttributeMapping buildJavaAttributeMappingFromMappingKey(String attributeMappingKey, JavaPersistentAttribute parent) { - return javaAttributeMappingProviderFromMappingKey(attributeMappingKey).buildMapping(parent, getJpaFactory()); - } - - public JavaAttributeMapping buildJavaAttributeMappingFromAnnotation(String mappingAnnotationName, JavaPersistentAttribute parent) { - return javaAttributeMappingProviderFromAnnotation(mappingAnnotationName).buildMapping(parent, getJpaFactory()); + return this.javaTypeMappingProviderFromAnnotation(mappingAnnotationName).buildMapping(parent, this.getJpaFactory()); } - public JavaAttributeMapping buildDefaultJavaAttributeMapping(JavaPersistentAttribute parent) { - return defaultJavaAttributeMappingProvider(parent).buildMapping(parent, getJpaFactory()); - } - - protected Iterator<JavaTypeMappingProvider> javaTypeMappingProviders() { + protected synchronized Iterator<JavaTypeMappingProvider> javaTypeMappingProviders() { if (this.javaTypeMappingProviders == null) { this.javaTypeMappingProviders = new ArrayList<JavaTypeMappingProvider>(); this.addJavaTypeMappingProvidersTo(this.javaTypeMappingProviders); @@ -156,7 +151,7 @@ public class GenericJpaPlatform implements JpaPlatform * The default includes the JPA spec-defined type mappings of * Entity, MappedSuperclass, and Embeddable */ - protected void addJavaTypeMappingProvidersTo(Collection<JavaTypeMappingProvider> providers) { + protected void addJavaTypeMappingProvidersTo(List<JavaTypeMappingProvider> providers) { providers.add(JavaEntityProvider.instance()); providers.add(JavaMappedSuperclassProvider.instance()); providers.add(JavaEmbeddableProvider.instance()); @@ -164,26 +159,41 @@ public class GenericJpaPlatform implements JpaPlatform } protected JavaTypeMappingProvider javaTypeMappingProviderFromMappingKey(String typeMappingKey) { - for (Iterator<JavaTypeMappingProvider> i = this.javaTypeMappingProviders(); i.hasNext(); ) { - JavaTypeMappingProvider provider = i.next(); + for (Iterator<JavaTypeMappingProvider> stream = this.javaTypeMappingProviders(); stream.hasNext(); ) { + JavaTypeMappingProvider provider = stream.next(); if (provider.getKey() == typeMappingKey) { return provider; } } - throw new IllegalArgumentException("Illegal type mapping key: " + typeMappingKey); + throw new IllegalArgumentException("Illegal type mapping key: " + typeMappingKey); //$NON-NLS-1$ } - + protected JavaTypeMappingProvider javaTypeMappingProviderFromAnnotation(String annotationName) { - for (Iterator<JavaTypeMappingProvider> i = this.javaTypeMappingProviders(); i.hasNext(); ) { - JavaTypeMappingProvider provider = i.next(); + for (Iterator<JavaTypeMappingProvider> stream = this.javaTypeMappingProviders(); stream.hasNext(); ) { + JavaTypeMappingProvider provider = stream.next(); if (provider.getAnnotationName() == annotationName) { return provider; } } - throw new IllegalArgumentException("Illegal annotation name: " + annotationName); + throw new IllegalArgumentException("Illegal annotation name: " + annotationName); //$NON-NLS-1$ + } + + + // **************** Attribute mapping providers ******************************** + + public JavaAttributeMapping buildJavaAttributeMappingFromMappingKey(String attributeMappingKey, JavaPersistentAttribute parent) { + return this.javaAttributeMappingProviderFromMappingKey(attributeMappingKey).buildMapping(parent, this.getJpaFactory()); } - - protected Iterator<JavaAttributeMappingProvider> javaAttributeMappingProviders() { + + public JavaAttributeMapping buildJavaAttributeMappingFromAnnotation(String mappingAnnotationName, JavaPersistentAttribute parent) { + return this.javaAttributeMappingProviderFromAnnotation(mappingAnnotationName).buildMapping(parent, this.getJpaFactory()); + } + + public JavaAttributeMapping buildDefaultJavaAttributeMapping(JavaPersistentAttribute parent) { + return this.defaultJavaAttributeMappingProvider(parent).buildMapping(parent, this.getJpaFactory()); + } + + protected synchronized Iterator<JavaAttributeMappingProvider> javaAttributeMappingProviders() { if (this.javaAttributeMappingProviders == null) { this.javaAttributeMappingProviders = new ArrayList<JavaAttributeMappingProvider>(); this.addJavaAttributeMappingProvidersTo(this.javaAttributeMappingProviders); @@ -196,7 +206,7 @@ public class GenericJpaPlatform implements JpaPlatform * The default includes the JPA spec-defined attribute mappings of * Basic, Id, Transient OneToOne, OneToMany, ManyToOne, ManyToMany, Embeddable, EmbeddedId, Version. */ - protected void addJavaAttributeMappingProvidersTo(Collection<JavaAttributeMappingProvider> providers) { + protected void addJavaAttributeMappingProvidersTo(List<JavaAttributeMappingProvider> providers) { providers.add(JavaBasicMappingProvider.instance()); providers.add(JavaEmbeddedMappingProvider.instance()); providers.add(JavaEmbeddedIdMappingProvider.instance()); @@ -210,69 +220,85 @@ public class GenericJpaPlatform implements JpaPlatform } protected JavaAttributeMappingProvider javaAttributeMappingProviderFromMappingKey(String attributeMappingKey) { - for (Iterator<JavaAttributeMappingProvider> i = this.javaAttributeMappingProviders(); i.hasNext(); ) { - JavaAttributeMappingProvider provider = i.next(); + for (Iterator<JavaAttributeMappingProvider> stream = this.javaAttributeMappingProviders(); stream.hasNext(); ) { + JavaAttributeMappingProvider provider = stream.next(); if (provider.getKey() == attributeMappingKey) { return provider; } } - throw new IllegalArgumentException("Illegal attribute mapping key: " + attributeMappingKey); + throw new IllegalArgumentException("Illegal attribute mapping key: " + attributeMappingKey); //$NON-NLS-1$ } - + protected JavaAttributeMappingProvider javaAttributeMappingProviderFromAnnotation(String annotationName) { - for (Iterator<JavaAttributeMappingProvider> i = this.javaAttributeMappingProviders(); i.hasNext(); ) { - JavaAttributeMappingProvider provider = i.next(); + for (Iterator<JavaAttributeMappingProvider> stream = this.javaAttributeMappingProviders(); stream.hasNext(); ) { + JavaAttributeMappingProvider provider = stream.next(); if (provider.getAnnotationName() == annotationName) { return provider; } } - throw new IllegalArgumentException("Illegal annotation name: " + annotationName); + throw new IllegalArgumentException("Illegal annotation name: " + annotationName); //$NON-NLS-1$ } - - protected ListIterator<DefaultJavaAttributeMappingProvider> defaultJavaAttributeMappingProviders() { + + protected synchronized ListIterator<DefaultJavaAttributeMappingProvider> defaultJavaAttributeMappingProviders() { if (this.defaultJavaAttributeMappingProviders == null) { this.defaultJavaAttributeMappingProviders = new ArrayList<DefaultJavaAttributeMappingProvider>(); this.addDefaultJavaAttributeMappingProvidersTo(this.defaultJavaAttributeMappingProviders); } return new CloneListIterator<DefaultJavaAttributeMappingProvider>(this.defaultJavaAttributeMappingProviders); } - + /** * Override this to specify more or different default attribute mapping providers. * The default includes the JPA spec-defined attribute mappings of * Embedded and Basic. */ protected void addDefaultJavaAttributeMappingProvidersTo(List<DefaultJavaAttributeMappingProvider> providers) { - providers.add(JavaEmbeddedMappingProvider.instance()); //bug 190344 need to test default embedded before basic + providers.add(JavaEmbeddedMappingProvider.instance()); // bug 190344 need to test default embedded before basic providers.add(JavaBasicMappingProvider.instance()); } protected JavaAttributeMappingProvider defaultJavaAttributeMappingProvider(JavaPersistentAttribute persistentAttribute) { - for (Iterator<DefaultJavaAttributeMappingProvider> i = this.defaultJavaAttributeMappingProviders(); i.hasNext(); ) { - DefaultJavaAttributeMappingProvider provider = i.next(); + for (Iterator<DefaultJavaAttributeMappingProvider> stream = this.defaultJavaAttributeMappingProviders(); stream.hasNext(); ) { + DefaultJavaAttributeMappingProvider provider = stream.next(); if (provider.defaultApplies(persistentAttribute)) { return provider; } } - - return nullAttributeMappingProvider(); + return this.getNullAttributeMappingProvider(); } - public String defaultJavaAttributeMappingKey(JavaPersistentAttribute persistentAttribute) { - return defaultJavaAttributeMappingProvider(persistentAttribute).getKey(); + public String getDefaultJavaAttributeMappingKey(JavaPersistentAttribute persistentAttribute) { + return this.defaultJavaAttributeMappingProvider(persistentAttribute).getKey(); } - + /** * the "null" attribute mapping is used when the attribute is neither * modified with a mapping annotation nor mapped by a "default" mapping */ - protected JavaAttributeMappingProvider nullAttributeMappingProvider() { + protected JavaAttributeMappingProvider getNullAttributeMappingProvider() { return JavaNullAttributeMappingProvider.instance(); } + // **************** Validation ********************************************* - + public void addToMessages(JpaProject project, List<IMessage> messages) { project.addToMessages(messages); } + + + // **************** Database ********************************************* + + public ConnectionProfileFactory getConnectionProfileFactory() { + return JptDbPlugin.instance().getConnectionProfileFactory(); + } + + public EntityGeneratorDatabaseAnnotationNameBuilder getEntityGeneratorDatabaseAnnotationNameBuilder() { + return GenericEntityGeneratorDatabaseAnnotationNameBuilder.instance(); + } + + public DatabaseFinder getDatabaseFinder() { + return DatabaseFinder.Default.instance(); + } + } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/DefaultJpaValidationMessages.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/DefaultJpaValidationMessages.java index 7c614af0c7..ae30b69460 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/DefaultJpaValidationMessages.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/DefaultJpaValidationMessages.java @@ -14,11 +14,9 @@ import org.eclipse.jpt.core.utility.TextRange; import org.eclipse.wst.validation.internal.core.Message; import org.eclipse.wst.validation.internal.provisional.core.IMessage; -public class DefaultJpaValidationMessages - implements JpaValidationMessages -{ +public class DefaultJpaValidationMessages { + private static String[] DEFAULT_PARMS = new String[0]; - private static TextRange DEFAULT_TEXT_RANGE = TextRange.Empty.instance(); public static IMessage buildMessage( @@ -38,12 +36,12 @@ public class DefaultJpaValidationMessages public static IMessage buildMessage( int severity, String messageId, String[] parms, Object targetObject, TextRange textRange) { - IMessage message = new Message(BUNDLE, severity, messageId, parms, targetObject); + IMessage message = new Message(JpaValidationMessages.BUNDLE_NAME, severity, messageId, parms, targetObject); if (textRange == null) { //log an exception and then continue without setting location information //At least the user will still get the validation message and will //be able to see other validation messages with valid textRanges - JptCorePlugin.log(new IllegalArgumentException("The textRange is null for messageId: " + messageId)); + JptCorePlugin.log(new IllegalArgumentException("Null text range for message ID: " + messageId)); //$NON-NLS-1$ } else { message.setLineNo(textRange.getLineNumber()); diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java index ebc641afc7..b944542c64 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidationMessages.java @@ -1,135 +1,77 @@ /******************************************************************************* - * Copyright (c) 2005, 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 - *******************************************************************************/ + * Copyright (c) 2005, 2008 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ package org.eclipse.jpt.core.internal.validation; -public interface JpaValidationMessages -{ - public static final String BUNDLE = "jpa_validation"; - +@SuppressWarnings("nls") +public interface JpaValidationMessages { + + public static final String BUNDLE_NAME = "jpa_validation"; public static final String PROJECT_NO_CONNECTION = "PROJECT_NO_CONNECTION"; - public static final String PROJECT_INACTIVE_CONNECTION = "PROJECT_INACTIVE_CONNECTION"; - public static final String PROJECT_NO_PERSISTENCE_XML = "PROJECT_NO_PERSISTENCE_XML"; - public static final String PROJECT_MULTIPLE_PERSISTENCE_XML = "PROJECT_MULTIPLE_PERSISTENCE_XML"; - public static final String PERSISTENCE_XML_INVALID_CONTENT = "PERSISTENCE_XML_INVALID_CONTENT"; - public static final String PERSISTENCE_NO_PERSISTENCE_UNIT = "PERSISTENCE_NO_PERSISTENCE_UNIT"; - public static final String PERSISTENCE_MULTIPLE_PERSISTENCE_UNITS = "PERSISTENCE_MULTIPLE_PERSISTENCE_UNITS"; - public static final String PERSISTENCE_UNIT_UNSPECIFIED_MAPPING_FILE = "PERSISTENCE_UNIT_UNSPECIFIED_MAPPING_FILE"; - public static final String PERSISTENCE_UNIT_NONEXISTENT_MAPPING_FILE = "PERSISTENCE_UNIT_NONEXISTENT_MAPPING_FILE"; - public static final String PERSISTENCE_UNIT_INVALID_MAPPING_FILE = "PERSISTENCE_UNIT_INVALID_MAPPING_FILE"; - public static final String PERSISTENCE_UNIT_DUPLICATE_MAPPING_FILE = "PERSISTENCE_UNIT_DUPLICATE_MAPPING_FILE"; - public static final String PERSISTENCE_UNIT_UNSPECIFIED_CLASS = "PERSISTENCE_UNIT_UNSPECIFIED_CLASS"; - public static final String PERSISTENCE_UNIT_NONEXISTENT_CLASS = "PERSISTENCE_UNIT_NONEXISTENT_CLASS"; - public static final String PERSISTENCE_UNIT_INVALID_CLASS = "PERSISTENCE_UNIT_INVALID_CLASS"; - public static final String PERSISTENCE_UNIT_DUPLICATE_CLASS = "PERSISTENCE_UNIT_DUPLICATE_CLASS"; - public static final String PERSISTENCE_UNIT_REDUNDANT_CLASS = "PERSISTENCE_UNIT_REDUNDANT_CLASS"; - public static final String GENERATOR_DUPLICATE_NAME = "GENERATOR_DUPLICATE_NAME"; - public static final String QUERY_DUPLICATE_NAME = "QUERY_DUPLICATE_NAME"; - public static final String ENTITY_MAPPINGS_MULTIPLE_METADATA = "ENTITY_MAPPINGS_MULTIPLE_METADATA"; - public static final String PERSISTENT_TYPE_UNSPECIFIED_CONTEXT = "PERSISTENT_TYPE_UNSPECIFIED_CONTEXT"; - public static final String PERSISTENT_TYPE_UNSPECIFIED_CLASS = "PERSISTENT_TYPE_UNSPECIFIED_CLASS"; - public static final String PERSISTENT_TYPE_UNRESOLVED_CLASS = "PERSISTENT_TYPE_UNRESOLVED_CLASS"; - public static final String ENTITY_NO_ID = "ENTITY_NO_ID"; - public static final String PERSISTENT_ATTRIBUTE_UNSPECIFIED_NAME = "PERSISTENT_ATTRIBUTE_UNSPECIFIED_NAME"; - public static final String PERSISTENT_ATTRIBUTE_UNRESOLVED_NAME = "PERSISTENT_ATTRIBUTE_UNRESOLVED_NAME"; - public static final String PERSISTENT_ATTRIBUTE_FINAL_FIELD = "PERSISTENT_ATTRIBUTE_FINAL_FIELD"; - public static final String PERSISTENT_ATTRIBUTE_PUBLIC_FIELD = "PERSISTENT_ATTRIBUTE_PUBLIC_FIELD"; - public static final String PERSISTENT_ATTRIBUTE_INVALID_MAPPING = "PERSISTENT_ATTRIBUTE_INVALID_MAPPING"; - public static final String MAPPING_UNRESOLVED_MAPPED_BY = "MAPPING_UNRESOLVED_MAPPED_BY"; - public static final String MAPPING_INVALID_MAPPED_BY = "MAPPING_INVALID_MAPPED_BY"; - public static final String MAPPING_MAPPED_BY_WITH_JOIN_TABLE = "MAPPING_MAPPED_BY_WITH_JOIN_TABLE"; - public static final String MAPPING_MAPPED_BY_ON_BOTH_SIDES = "MAPPING_MAPPED_BY_ON_BOTH_SIDES"; - public static final String ID_MAPPING_UNRESOLVED_GENERATOR_NAME = "ID_MAPPING_UNRESOLVED_GENERATOR_NAME"; - public static final String TABLE_UNRESOLVED_SCHEMA = "TABLE_UNRESOLVED_SCHEMA"; - public static final String TABLE_UNRESOLVED_NAME = "TABLE_UNRESOLVED_NAME"; - public static final String SECONDARY_TABLE_UNRESOLVED_SCHEMA = "SECONDARY_TABLE_UNRESOLVED_SCHEMA"; - public static final String SECONDARY_TABLE_UNRESOLVED_NAME = "SECONDARY_TABLE_UNRESOLVED_NAME"; - public static final String JOIN_TABLE_UNRESOLVED_SCHEMA = "JOIN_TABLE_UNRESOLVED_SCHEMA"; - public static final String VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA = "VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA"; - public static final String JOIN_TABLE_UNRESOLVED_NAME = "JOIN_TABLE_UNRESOLVED_NAME"; - public static final String VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME"; - public static final String COLUMN_UNRESOLVED_TABLE = "COLUMN_UNRESOLVED_TABLE"; - public static final String VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_TABLE = "VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_TABLE"; - public static final String VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_TABLE = "VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_TABLE"; - public static final String COLUMN_UNRESOLVED_NAME = "COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME"; - public static final String JOIN_COLUMN_UNRESOLVED_TABLE = "JOIN_COLUMN_UNRESOLVED_TABLE"; - public static final String VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_TABLE = "VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_TABLE"; - public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_TABLE = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_TABLE"; - public static final String JOIN_COLUMN_UNRESOLVED_NAME = "JOIN_COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME"; - public static final String JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME = "JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ATTRIBUTE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ATTRIBUTE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME"; - public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME"; - public static final String GENERATED_VALUE_UNRESOLVED_GENERATOR = "GENERATED_VALUE_UNRESOLVED_GENERATOR"; - public static final String PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME = "PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME"; - public static final String PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME = "PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME"; } diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JPA.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JPA.java index 71cdfda387..25328896bb 100644 --- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JPA.java +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/java/JPA.java @@ -19,11 +19,13 @@ package org.eclipse.jpt.core.resource.java; * pioneering adopters on the understanding that any code that uses this API * will almost certainly be broken (repeatedly) as the API evolves. */ +// TODO move to utility? +@SuppressWarnings("nls") public interface JPA { // JPA package String PACKAGE = "javax.persistence"; - String PACKAGE_ = PACKAGE + "."; + String PACKAGE_ = PACKAGE + '.'; // ********** API ********** @@ -218,14 +220,14 @@ public interface JPA { // JPA enums String GENERATION_TYPE = PACKAGE_ + "GenerationType"; - String GENERATION_TYPE_ = GENERATION_TYPE + "."; + String GENERATION_TYPE_ = GENERATION_TYPE + '.'; String GENERATION_TYPE__AUTO = GENERATION_TYPE_ + "AUTO"; String GENERATION_TYPE__IDENTITY = GENERATION_TYPE_ + "IDENTITY"; String GENERATION_TYPE__SEQUENCE = GENERATION_TYPE_ + "SEQUENCE"; String GENERATION_TYPE__TABLE = GENERATION_TYPE_ + "TABLE"; String CASCADE_TYPE = PACKAGE_ + "CascadeType"; - String CASCADE_TYPE_ = CASCADE_TYPE + "."; + String CASCADE_TYPE_ = CASCADE_TYPE + '.'; String CASCADE_TYPE__ALL = CASCADE_TYPE_ + "ALL"; String CASCADE_TYPE__MERGE = CASCADE_TYPE_ + "MERGE"; String CASCADE_TYPE__PERSIST = CASCADE_TYPE_ + "PERSIST"; @@ -233,39 +235,39 @@ public interface JPA { String CASCADE_TYPE__REMOVE = CASCADE_TYPE_ + "REMOVE"; String DISCRIMINATOR_TYPE = PACKAGE_ + "DiscriminatorType"; - String DISCRIMINATOR_TYPE_ = DISCRIMINATOR_TYPE + "."; + String DISCRIMINATOR_TYPE_ = DISCRIMINATOR_TYPE + '.'; String DISCRIMINATOR_TYPE__CHAR = DISCRIMINATOR_TYPE_ + "CHAR"; String DISCRIMINATOR_TYPE__INTEGER = DISCRIMINATOR_TYPE_ + "INTEGER"; String DISCRIMINATOR_TYPE__STRING = DISCRIMINATOR_TYPE_ + "STRING"; String ENUM_TYPE = PACKAGE_ + "EnumType"; - String ENUM_TYPE_ = ENUM_TYPE + "."; + String ENUM_TYPE_ = ENUM_TYPE + '.'; String ENUM_TYPE__ORDINAL = ENUM_TYPE_ + "ORDINAL"; String ENUM_TYPE__STRING = ENUM_TYPE_ + "STRING"; String FETCH_TYPE = PACKAGE_ + "FetchType"; - String FETCH_TYPE_ = FETCH_TYPE + "."; + String FETCH_TYPE_ = FETCH_TYPE + '.'; String FETCH_TYPE__EAGER = FETCH_TYPE_ + "EAGER"; String FETCH_TYPE__LAZY = FETCH_TYPE_ + "LAZY"; String FLUSH_MODE_TYPE = PACKAGE_ + "FlushModeType"; - String FLUSH_MODE_TYPE_ = FLUSH_MODE_TYPE + "."; + String FLUSH_MODE_TYPE_ = FLUSH_MODE_TYPE + '.'; String FLUSH_MODE_TYPE__AUTO = FLUSH_MODE_TYPE_ + "AUTO"; String FLUSH_MODE_TYPE__COMMIT = FLUSH_MODE_TYPE_ + "COMMIT"; String INHERITANCE_TYPE = PACKAGE_ + "InheritanceType"; - String INHERITANCE_TYPE_ = INHERITANCE_TYPE + "."; + String INHERITANCE_TYPE_ = INHERITANCE_TYPE + '.'; String INHERITANCE_TYPE__JOINED = INHERITANCE_TYPE_ + "JOINED"; String INHERITANCE_TYPE__SINGLE_TABLE = INHERITANCE_TYPE_ + "SINGLE_TABLE"; String INHERITANCE_TYPE__TABLE_PER_CLASS = INHERITANCE_TYPE_ + "TABLE_PER_CLASS"; String PERSISTENCE_CONTEXT_TYPE = PACKAGE_ + "PersistenceContextType"; - String PERSISTENCE_CONTEXT_TYPE_ = PERSISTENCE_CONTEXT_TYPE + "."; + String PERSISTENCE_CONTEXT_TYPE_ = PERSISTENCE_CONTEXT_TYPE + '.'; String PERSISTENCE_CONTEXT_TYPE__EXTENDED = PERSISTENCE_CONTEXT_TYPE_ + "EXTENDED"; String PERSISTENCE_CONTEXT_TYPE__TRANSACTION = PERSISTENCE_CONTEXT_TYPE_ + "TRANSACTION"; String TEMPORAL_TYPE = PACKAGE_ + "TemporalType"; - String TEMPORAL_TYPE_ = TEMPORAL_TYPE + "."; + String TEMPORAL_TYPE_ = TEMPORAL_TYPE + '.'; String TEMPORAL_TYPE__DATE = TEMPORAL_TYPE_ + "DATE"; String TEMPORAL_TYPE__TIME = TEMPORAL_TYPE_ + "TIME"; String TEMPORAL_TYPE__TIMESTAMP = TEMPORAL_TYPE_ + "TIMESTAMP"; @@ -290,7 +292,7 @@ public interface JPA { // JPA SPI package String SPI_PACKAGE = PACKAGE_ + "spi"; - String SPI_PACKAGE_ = SPI_PACKAGE + "."; + String SPI_PACKAGE_ = SPI_PACKAGE + '.'; // JPA SPI interfaces String ENTITY_MANAGER_FACTORY_PROVIDER = SPI_PACKAGE_ + "EntityManagerFactoryProvider"; diff --git a/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java b/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java index 13b277f200..ae67ad1cf6 100644 --- a/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java +++ b/jpa/plugins/org.eclipse.jpt.db.ui/src/org/eclipse/jpt/db/ui/internal/DTPUiTools.java @@ -17,85 +17,99 @@ import org.eclipse.datatools.connectivity.internal.ConnectionProfileManager; import org.eclipse.datatools.connectivity.internal.ui.wizards.CPWizardNode; import org.eclipse.datatools.connectivity.internal.ui.wizards.NewCPWizard; import org.eclipse.datatools.connectivity.internal.ui.wizards.ProfileWizardProvider; +import org.eclipse.datatools.connectivity.ui.wizards.IProfileWizardProvider; import org.eclipse.datatools.connectivity.ui.wizards.IWizardCategoryProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; /** - * ConnectionProfileUiTools + * DTP UI tools */ public class DTPUiTools { - private static final String DATABASE_CATEGORY_ID = "org.eclipse.datatools.connectivity.db.category"; //$NON-NLS-1$ - /** * Launch the DTP New Connection Profile wizard to create a new database connection profile. * - * Returns the name of the added profile, or null if the wizard is cancelled. ConnectionProfileRepository - * can be used to retrieve the added connection profile. + * Returns the name of the added profile, or null if the wizard was cancelled. + * The name can be used to build a Dali connection profile from + * JptDbPlugin.getConnectionProfileFactory().buildConnectionProfile(String). */ - public static String createNewProfile() { - NewCPWizard wizard; - WizardDialog wizardDialog; - + public static String createNewConnectionProfile() { // Filter datasource category - ViewerFilter viewerFilter = new ViewerFilter() { - - @Override - public boolean select( Viewer viewer, Object parentElement, Object element) { - - CPWizardNode wizardNode = ( CPWizardNode) element; - if( !( wizardNode.getProvider() instanceof IWizardCategoryProvider)) { - ICategory cat = ConnectionProfileManager.getInstance().getProvider( - (( ProfileWizardProvider) wizardNode.getProvider()).getProfile()).getCategory(); - - // Only display wizards belong to database category - while( cat != null) { - if( cat.getId().equals(DATABASE_CATEGORY_ID)) - return true; - cat = cat.getParent(); - } - } - return false; - } - }; - wizard = new NewCPWizard( viewerFilter, null); - Shell currentShell = Display.getCurrent().getActiveShell(); - wizardDialog = new WizardDialog( currentShell, wizard); - wizardDialog.setBlockOnOpen( true); - + NewCPWizard wizard = new NewCPWizard(new LocalViewerFilter(), null); + WizardDialog wizardDialog = new WizardDialog(Display.getCurrent().getActiveShell(), wizard); + wizardDialog.setBlockOnOpen(true); + LocalProfileListener listener = new LocalProfileListener(); - ProfileManager.getInstance().addProfileListener( listener); - - if( wizardDialog.open() == Window.CANCEL) { - ProfileManager.getInstance().removeProfileListener( listener); - return null; + ProfileManager.getInstance().addProfileListener(listener); + + String newCPName = null; + if (wizardDialog.open() == Window.OK) { + // assume the last added profile is the one we want + newCPName = listener.addedProfile.getName(); } - IConnectionProfile addedProfile = listener.addedProfile; - ProfileManager.getInstance().removeProfileListener( listener); - - return addedProfile.getName(); + ProfileManager.getInstance().removeProfileListener(listener); + + return newCPName; } + + // ********** DTP profile listener ********** + + /** + * This listener simply holds on to the most recently added connection + * profile. + */ static class LocalProfileListener implements IProfileListener { IConnectionProfile addedProfile; - public void profileAdded( IConnectionProfile profile) { - addedProfile = profile; + public void profileAdded(IConnectionProfile profile) { + this.addedProfile = profile; } - public void profileChanged( IConnectionProfile profile) { + public void profileChanged(IConnectionProfile profile) { // do nothing } - public void profileDeleted( IConnectionProfile profile) { + public void profileDeleted(IConnectionProfile profile) { // do nothing } } - + + + // ********** viewer filter ********** + + static class LocalViewerFilter extends ViewerFilter { + + private static final String DATABASE_CATEGORY_ID = "org.eclipse.datatools.connectivity.db.category"; //$NON-NLS-1$ + + LocalViewerFilter() { + super(); + } + + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + CPWizardNode wizardNode = (CPWizardNode) element; + IProfileWizardProvider wizardProvider = wizardNode.getProvider(); + if (wizardProvider instanceof IWizardCategoryProvider) { + return false; + } + ICategory category = ConnectionProfileManager.getInstance().getProvider( + ((ProfileWizardProvider) wizardProvider).getProfile()).getCategory(); + + // Only display wizards belong to database category + while (category != null) { + if (category.getId().equals(DATABASE_CATEGORY_ID)) { + return true; + } + category = category.getParent(); + } + return false; + } + } + } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Catalog.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Catalog.java index 2db19a83af..5c6da7058d 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Catalog.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Catalog.java @@ -20,11 +20,8 @@ package org.eclipse.jpt.db; * * This interface is not intended to be implemented by clients. */ -public interface Catalog extends Comparable<Catalog> { - - /** - * Return the catalog's name. - */ - String getName(); - +public interface Catalog + extends SchemaContainer, Comparable<Catalog> +{ + // nothing yet } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Column.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Column.java index 99af66db0e..e631a6da75 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Column.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Column.java @@ -22,42 +22,37 @@ import org.eclipse.jpt.utility.JavaType; * * This interface is not intended to be implemented by clients. */ -public interface Column extends Comparable<Column> { - +public interface Column + extends DatabaseObject, Comparable<Column> +{ /** - * Return the column's name. + * Return the column's table. */ - String getName(); + Table getTable(); /** - * Return the name of the column's datatype. + * Return whether the column is part of it's table's primary key. */ - String getDataTypeName(); + boolean isPrimaryKeyColumn(); /** - * Return a Java-appropriate version of the column's name. + * Return whether the column is part of one of it's table's foreign keys. */ - String getJavaFieldName(); + boolean isForeignKeyColumn(); /** - * Return whether the column's name matches the specified Java identifier, - * respecting the database's case-sensitivity. + * Return the name of the column's datatype. */ - boolean matchesJavaFieldName(String javaFieldName); + String getDataTypeName(); /** - * Return a Java type declaration that is reasonably - * similar to the column's data type and suitable for use as a - * primary key field. + * Return whether the column's datatype is a LOB type + * (i.e. BLOB, CLOB, or NCLOB). */ - String getPrimaryKeyJavaTypeDeclaration(); + boolean dataTypeIsLOB(); - /** - * Return a Java type that is reasonably - * similar to the column's data type and suitable for use as a - * primary key field. - */ - JavaType getPrimaryKeyJavaType(); + + // ********** Java type ********** /** * Return a Java type declaration that is reasonably @@ -72,9 +67,17 @@ public interface Column extends Comparable<Column> { JavaType getJavaType(); /** - * Return whether the column's datatype is a LOB type - * (i.e. BLOB, CLOB, or NCLOB). + * Return a Java type declaration that is reasonably + * similar to the column's data type and suitable for use as a + * primary key field. */ - boolean dataTypeIsLOB(); + String getPrimaryKeyJavaTypeDeclaration(); + + /** + * Return a Java type that is reasonably + * similar to the column's data type and suitable for use as a + * primary key field. + */ + JavaType getPrimaryKeyJavaType(); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfile.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfile.java index 8388f58ed4..126ea9f1d7 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfile.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfile.java @@ -23,34 +23,19 @@ import org.eclipse.datatools.connectivity.drivers.jdbc.IJDBCDriverDefinitionCons * * This interface is not intended to be implemented by clients. */ -public interface ConnectionProfile extends Comparable<ConnectionProfile> { +public interface ConnectionProfile + extends DatabaseObject, Comparable<ConnectionProfile> +{ - /** - * Return the connection profile's name. - */ - String getName(); + // ********** properties ********** /** * Return the connection profile's database. - * Return a "null" database if the connection profile is inactive. + * Return null if the connection profile is inactive. */ Database getDatabase(); /** - * Return the connection profile's "default" catalog. - * Return null if the connection profile's database does not support - * catalogs. - */ - Catalog getDefaultCatalog(); - - /** - * Return the connection profile's default schema. - * In most cases the default schema's name will match the user name. - * It may be null. - */ - Schema getDefaultSchema(); - - /** * Return ID of the provider managing the DTP profile. */ String getProviderID(); @@ -88,7 +73,7 @@ public interface ConnectionProfile extends Comparable<ConnectionProfile> { /** * Return the default connection URL. */ - String getUrl(); + String getURL(); /** * Return the default user name. @@ -111,15 +96,25 @@ public interface ConnectionProfile extends Comparable<ConnectionProfile> { */ String getDriverJarList(); + + // ********** connection ********** + /** * Return whether the profile is either connected to a live database * session or working off-line (i.e. it has access to meta-data). * @see isConnected() - * @see isWorkingOfflin() + * @see isWorkingOffline() */ boolean isActive(); /** + * Return whether the profile is neither connected to a live database + * session nor working off-line (i.e. it has access to meta-data). + * @see isActive() + */ + boolean isInactive(); + + /** * Return whether the profile is connected to a live database session * (i.e. the meta-data comes from the database), as opposed to working * off-line. @@ -128,15 +123,28 @@ public interface ConnectionProfile extends Comparable<ConnectionProfile> { boolean isConnected(); /** + * Return whether the profile is not connected to a live database session + * (i.e. the meta-data comes from the database), as opposed to working + * off-line. + * @see #isConnected() + */ + boolean isDisconnected(); + + /** * Connect to the database. + * @see #disconnect() */ void connect(); /** * Disconnect from the database. + * @see #connect() */ void disconnect(); + + // ********** off-line support ********** + /** * Return whether the profile is working off-line (i.e. the meta-data * comes from a local cache), as opposed to connected to a live @@ -169,10 +177,8 @@ public interface ConnectionProfile extends Comparable<ConnectionProfile> { */ IStatus workOffline(); - /** - * Return whether the connection profile is a "null" connection profile. - */ - boolean isNull(); + + // ********** listeners ********** /** * Add the specified connection listener to the connection profile. @@ -184,6 +190,9 @@ public interface ConnectionProfile extends Comparable<ConnectionProfile> { */ void removeConnectionListener(ConnectionListener listener); + + // ********** constants ********** + String CONNECTION_PROFILE_TYPE = "org.eclipse.datatools.connectivity.db.generic.connectionProfile"; //$NON-NLS-1$ String DRIVER_DEFINITION_PROP_ID = "org.eclipse.datatools.connectivity.driverDefinitionID"; //$NON-NLS-1$ String DRIVER_DEFINITION_TYPE_PROP_ID = "org.eclipse.datatools.connectivity.drivers.defnType"; //$NON-NLS-1$ diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileAdapter.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileAdapter.java index fb5c601a25..648daa5bf6 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileAdapter.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileAdapter.java @@ -20,11 +20,15 @@ package org.eclipse.jpt.db; */ public class ConnectionProfileAdapter implements ConnectionProfileListener { - public void connectionProfileChanged(ConnectionProfile profile) { + public void connectionProfileAdded(String name) { // do nothing } - public void connectionProfileReplaced(ConnectionProfile oldProfile, ConnectionProfile newProfile) { + public void connectionProfileRemoved(String name) { + // do nothing + } + + public void connectionProfileRenamed(String oldName, String newName) { // do nothing } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileRepository.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileFactory.java index 8f37291f78..4bff72eae2 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileRepository.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileFactory.java @@ -12,7 +12,7 @@ package org.eclipse.jpt.db; import java.util.Iterator; /** - * Database connection profile repository + * Database connection profile factory * * Provisional API: This interface is part of an interim API that is still * under development and expected to change significantly before reaching @@ -22,38 +22,38 @@ import java.util.Iterator; * * This interface is not intended to be implemented by clients. */ -public interface ConnectionProfileRepository { +public interface ConnectionProfileFactory { /** - * Return the repository's connection profiles. - */ - Iterator<ConnectionProfile> connectionProfiles(); - - /** - * Return the number of connection profiles in the repository. - */ - int connectionProfilesSize(); - - /** - * Return the repository's connection profile names. + * Return the names of the DTP connection profiles the factory can wrap with + * new connection profiles. */ Iterator<String> connectionProfileNames(); /** - * Return whether the repository contains a connection profile - * with the specified name. + * Build and return a connection profile that wraps the DTP connection + * profile with the specified name. + * Return null if there is no DTP connection profile with the specified + * name. + * Use the specified database finder to allow clients to control how + * database objects are found based on their names. */ - boolean containsConnectionProfileNamed(String name); + ConnectionProfile buildConnectionProfile(String name, DatabaseFinder finder); /** - * Return the connection profile with the specified name. - * Return a "null" connection profile if the repository does not - * have a connection profile with the specified name. + * Build and return a connection profile that wraps the DTP connection + * profile with the specified name. + * Return null if there is no DTP connection profile with the specified + * name. + * Clients should use this method when a JPA platform is unavailable + * (e.g. during project creation). The returned connection profile will + * not be able to search for database objects by any names other than + * those supplied by the factory. */ - ConnectionProfile connectionProfileNamed(String name); + ConnectionProfile buildConnectionProfile(String name); /** - * Add a listener that will be notified of changes to the repository's + * Add a listener that will be notified of changes to the DTP * connection profiles. */ void addConnectionProfileListener(ConnectionProfileListener listener); diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileListener.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileListener.java index 89f6207998..66844b1380 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileListener.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ConnectionProfileListener.java @@ -10,7 +10,7 @@ package org.eclipse.jpt.db; /** - * A ProfileListener is notified of any changes to the connection profiles. + * A ProfileListener is notified of any changes to the DTP connection profiles. * * @see org.eclipse.datatools.connectivity.IProfileListener * @@ -23,17 +23,18 @@ package org.eclipse.jpt.db; public interface ConnectionProfileListener { /** - * The specified old profile has been replaced with the specified - * new profile. The old profile is a "null" profile when a profile is - * added. The new profile is a "null" profile when a profile is - * removed. + * The specified profile has been added. */ - public void connectionProfileReplaced(ConnectionProfile oldProfile, ConnectionProfile newProfile); + public void connectionProfileAdded(String name); /** - * The specified profile has been modified. Modification includes - * changes to any properties, the name, auto-connect flag, etc. + * The specified profile has been removed. */ - public void connectionProfileChanged(ConnectionProfile profile); + public void connectionProfileRemoved(String name); + + /** + * The specified profile has been renamed. + */ + public void connectionProfileRenamed(String oldName, String newName); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Database.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Database.java index e4e19babc3..d4f3c1b9e1 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Database.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Database.java @@ -10,7 +10,6 @@ package org.eclipse.jpt.db; import java.util.Iterator; -import org.eclipse.datatools.connectivity.sqm.core.definition.DatabaseDefinition; /** * Database @@ -23,12 +22,11 @@ import org.eclipse.datatools.connectivity.sqm.core.definition.DatabaseDefinition * * This interface is not intended to be implemented by clients. */ -public interface Database extends SchemaContainer, Comparable<Database> { +public interface Database + extends SchemaContainer, Comparable<Database> +{ - /** - * Return the database's name. - */ - String getName(); + // ********** properties ********** /** * Return the database's vendor. @@ -41,14 +39,14 @@ public interface Database extends SchemaContainer, Comparable<Database> { String getVersion(); /** - * Return whether the database's identifiers are case-sensitive. + * Return the database's default schema. + * In most cases the default schema's name will match the user name. + * It may be null. */ - boolean isCaseSensitive(); + Schema getDefaultSchema(); - /** - * Return the database's DTP database definition. - */ - DatabaseDefinition getDtpDefinition(); + + // ********** catalogs ********** /** * Return whether the database supports catalogs. @@ -71,20 +69,26 @@ public interface Database extends SchemaContainer, Comparable<Database> { Iterator<String> catalogNames(); /** - * Return whether the database contains a catalog with the specified name, - * respecting the database's case-sensitivity. + * Return the database's "default" catalog. + * Return null if the database does not support catalogs. */ - boolean containsCatalogNamed(String name); + Catalog getDefaultCatalog(); /** - * Return the catalog in the database with the specified name, - * respecting the database's case-sensitivity. + * Return the catalog with specified name. The name should be an SQL + * identifier (i.e. quoted when case-sensitive, unquoted when + * case-insensitive). */ - Catalog catalogNamed(String name); + Catalog getCatalogNamed(String name); + + + // ********** search utility ********** /** - * Return the database's "default" catalog. + * Return the database object from the specified list with specified name. + * The name should be an SQL identifier (i.e. quoted when case-sensitive, + * unquoted when case-insensitive). */ - Catalog getDefaultCatalog(); + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseFinder.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseFinder.java new file mode 100644 index 0000000000..d8cf20e36f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseFinder.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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.db; + +/** + * This interface allows clients of the Dali db package to plug in a custom + * strategy for comparing an identifier to the names of a collection of + * database objects. + * + * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + * + * This interface is not intended to be implemented by clients. + */ +public interface DatabaseFinder { + + /** + * Return the database object with the specified name from the specified list. + */ + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name, DefaultCallback defaultCallback); + + /** + * The platform-provided finder is passed a "default" callback that can be + * used if appropriate. + */ + interface DefaultCallback { + + /** + * Return the database object with the specified name from the specified list. + */ + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name); + + } + + /** + * This finder searches for an exact match. + */ + final class Simple implements DatabaseFinder { + public static final DatabaseFinder INSTANCE = new Simple(); + public static DatabaseFinder instance() { + return INSTANCE; + } + // ensure single instance + private Simple() { + super(); + } + // search for an exact match on the name + public <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name, DefaultCallback defaultCallback) { + for (T databaseObject : databaseObjects) { + if (databaseObject.getName().equals(name)) { + return databaseObject; + } + } + return null; + } + @Override + public String toString() { + return "DatabaseFinder.Default"; //$NON-NLS-1$ + } + } + + /** + * This finder uses the passed in callback to search the list of database objects. + */ + final class Default implements DatabaseFinder { + public static final DatabaseFinder INSTANCE = new Default(); + public static DatabaseFinder instance() { + return INSTANCE; + } + // ensure single instance + private Default() { + super(); + } + // simply use the callback + public <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name, DefaultCallback defaultCallback) { + return defaultCallback.getDatabaseObjectNamed(databaseObjects, name); + } + @Override + public String toString() { + return "DatabaseFinder.Default"; //$NON-NLS-1$ + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseObject.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseObject.java new file mode 100644 index 0000000000..5b25256f3a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/DatabaseObject.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.db; + +/** + * Common behavior to all database objects + * + * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + * + * This interface is not intended to be implemented by clients. + */ +public interface DatabaseObject { + + /** + * Return the database object's name. + */ + String getName(); + + /** + * Given the name of a Java member and the database object to which it is + * mapped, build and return a string to be used as the value for the member's + * database object annotation's 'name' element. Return null if the member + * maps to the database object by default. + */ + String getAnnotationIdentifier(String javaIdentifier); + + /** + * Return a string to be used as the value for the member's + * database object annotation's 'name' element. + */ + String getAnnotationIdentifier(); + + /** + * Return the database object's connection profile. + */ + ConnectionProfile getConnectionProfile(); + +} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ForeignKey.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ForeignKey.java index 3215cfdfd4..0406b42eba 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ForeignKey.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/ForeignKey.java @@ -22,12 +22,11 @@ import java.util.Iterator; * * This interface is not intended to be implemented by clients. */ -public interface ForeignKey extends Comparable<ForeignKey> { +public interface ForeignKey + extends DatabaseObject, Comparable<ForeignKey> +{ - /** - * Return the foreign key's name. - */ - String getName(); + // ********** tables ********** /** * Return the foreign key's "base" table. @@ -39,67 +38,84 @@ public interface ForeignKey extends Comparable<ForeignKey> { */ Table getReferencedTable(); + + // ********** column pairs ********** + /** * Return the foreign key's column pairs. - * @see ColumnPair */ Iterator<ColumnPair> columnPairs(); /** - * Return the foreign key's single column pair. Throw an - * IllegalStateException if the foreign key has more than one column pair. + * Return the size of the foreign key's column pairs. */ - ColumnPair columnPair(); + int columnPairsSize(); /** - * Return the size of the foreign key's column pairs. - * @see ColumnPair + * Return the foreign key's single column pair. Throw an + * IllegalStateException if the foreign key has more than one column pair. */ - int columnPairsSize(); + ColumnPair getColumnPair(); /** * Return the foreign key's "base" columns. - * @see ColumnPair */ Iterator<Column> baseColumns(); /** - * Return the foreign key's "base" columns that are not part of - * the base table's primary key. - * @see ColumnPair + * Return the foreign key's "base" columns that are not part of the base + * table's primary key. (The non-primary key base columns are not used to + * generate basic attributes during entity generation.) */ Iterator<Column> nonPrimaryKeyBaseColumns(); /** * Return the foreign key's "referenced" columns. - * @see ColumnPair */ Iterator<Column> referencedColumns(); /** - * Return a Java-appropriate name for a field that holds the entity - * mapped to the foreign key's "referenced" table. + * Return whether the foreign key references the primary key of the + * "referenced" table and that primary key has only a single column. + * This can be used when determining JPA defaults. */ - String getJavaFieldName(); + boolean referencesSingleColumnPrimaryKey(); + + + // ********** JPA support ********** /** - * Return whether the foreign key's default Java field name matches the - * specified Java identifier, respecting the database's case-sensitivity. + * Return an appropriate name for an attribute that holds the entity + * mapped to the foreign key's "referenced" table. */ - boolean defaultMatchesJavaFieldName(String javaFieldName); + String getAttributeName(); /** - * Return whether the foreign key is the default for the specified Java - * field name, respecting the database's case-sensitivity. + * If the name of the "base" column adheres to the JPA spec for a + * default mapping (i.e. it ends with an underscore followed by the name + * of the "referenced" column, and the "referenced" column is the single + * primary key column of the "referenced" table), return the corresponding + * default attribute name: + * ForeignKey(EMP.CUBICLE_ID => CUBICLE.ID) => "CUBICLE" + * Return a null if it does not adhere to the JPA spec: + * ForeignKey(EMP.CUBICLE_ID => CUBICLE.CUBICLE_ID) => null + * ForeignKey(EMP.CUBICLE => CUBICLE.ID) => null */ - boolean isDefaultFor(String javaFieldName); + String getDefaultAttributeName(); /** - * Return whether the foreign key references the primary key of the - * "referenced" table and that primary key has only a single column. + * Given the name of an attribute (field or property) that is mapped to the + * foreign key, + * 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. + * Precondition: The foreign key consists of a single column pair whose + * referenced column is the single-column primary key of the foreign + * key's referenced table. */ - boolean referencesSingleColumnPrimaryKey(); + String getJoinColumnAnnotationIdentifier(String attributeName); + // ********** column pair interface ********** /** * Pair up the foreign key's column pairs, matching each "base" column with @@ -111,12 +127,12 @@ public interface ForeignKey extends Comparable<ForeignKey> { /** * Return the column pair's "base" column. */ - Column baseColumn(); + Column getBaseColumn(); /** * Return the column pair's "referenced" column. */ - Column referencedColumn(); + Column getReferencedColumn(); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/JptDbPlugin.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/JptDbPlugin.java index 00aa478fb9..346de5ba65 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/JptDbPlugin.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/JptDbPlugin.java @@ -10,12 +10,12 @@ package org.eclipse.jpt.db; import org.eclipse.core.runtime.Plugin; -import org.eclipse.jpt.db.internal.DTPConnectionProfileRepository; +import org.eclipse.jpt.db.internal.DTPConnectionProfileFactory; import org.osgi.framework.BundleContext; /** * The JPT DB plug-in lifecycle implementation. - * Globally available connection profile repository. + * Globally available connection profile factory. * * Provisional API: This class is part of an interim API that is still * under development and expected to change significantly before reaching @@ -24,7 +24,7 @@ import org.osgi.framework.BundleContext; * will almost certainly be broken (repeatedly) as the API evolves. */ public class JptDbPlugin extends Plugin { - private DTPConnectionProfileRepository connectionProfileRepository; + private DTPConnectionProfileFactory connectionProfileFactory; private static JptDbPlugin INSTANCE; // sorta-final @@ -49,8 +49,8 @@ public class JptDbPlugin extends Plugin { @Override public void start(BundleContext context) throws Exception { super.start(context); - this.connectionProfileRepository = DTPConnectionProfileRepository.instance(); - this.connectionProfileRepository.start(); + this.connectionProfileFactory = DTPConnectionProfileFactory.instance(); + this.connectionProfileFactory.start(); } /** @@ -58,14 +58,14 @@ public class JptDbPlugin extends Plugin { */ @Override public void stop(BundleContext context) throws Exception { - this.connectionProfileRepository.stop(); - this.connectionProfileRepository = null; + this.connectionProfileFactory.stop(); + this.connectionProfileFactory = null; INSTANCE = null; super.stop(context); } - public ConnectionProfileRepository getConnectionProfileRepository() { - return this.connectionProfileRepository; + public ConnectionProfileFactory getConnectionProfileFactory() { + return this.connectionProfileFactory; } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Schema.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Schema.java index 2b13ecede0..7d82c9e0ce 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Schema.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Schema.java @@ -23,12 +23,17 @@ import java.util.Iterator; * * This interface is not intended to be implemented by clients. */ -public interface Schema extends Comparable<Schema> { - +public interface Schema + extends DatabaseObject, Comparable<Schema> +{ /** - * Return the schema's name. + * Return the schema's catalog. Return null if the schema's database does + * not support catalogs. */ - String getName(); + Catalog getCatalog(); + + + // ********** tables ********** /** * Return the schema's tables. @@ -46,16 +51,14 @@ public interface Schema extends Comparable<Schema> { Iterator<String> tableNames(); /** - * Return whether the schema contains a table with the specified name, - * respecting the database's case-sensitivity. + * Return the table with specified name. The name should be an SQL + * identifier (i.e. quoted when case-sensitive, unquoted when + * case-insensitive). */ - boolean containsTableNamed(String name); + Table getTableNamed(String name); - /** - * Return the table in the schema with the specified name, - * respecting the database's case-sensitivity. - */ - Table tableNamed(String name); + + // ********** sequences ********** /** * Return the schema's sequences. @@ -73,15 +76,10 @@ public interface Schema extends Comparable<Schema> { Iterator<String> sequenceNames(); /** - * Return whether the schema contains a sequence with the specified name, - * respecting the database's case-sensitivity. - */ - boolean containsSequenceNamed(String name); - - /** - * Return the sequence in the schema with the specified name, - * respecting the database's case-sensitivity. + * Return the sequence with specified name. The name should be an SQL + * identifier (i.e. quoted when case-sensitive, unquoted when + * case-insensitive). */ - Sequence sequenceNamed(String name); + Sequence getSequenceNamed(String name); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/SchemaContainer.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/SchemaContainer.java index 52895619bf..c814945bc2 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/SchemaContainer.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/SchemaContainer.java @@ -22,7 +22,9 @@ import java.util.Iterator; * * This interface is not intended to be implemented by clients. */ -public interface SchemaContainer { +public interface SchemaContainer + extends DatabaseObject +{ /** * Return the container's schemata. @@ -40,15 +42,10 @@ public interface SchemaContainer { Iterator<String> schemaNames(); /** - * Return whether the container contains a schema with the specified name, - * respecting the database's case-sensitivity. + * Return the schema with specified name. The name should be an SQL + * identifier (i.e. quoted when case-sensitive, unquoted when + * case-insensitive). */ - boolean containsSchemaNamed(String name); - - /** - * Return the schema in the container with the specified name, - * respecting the database's case-sensitivity. - */ - Schema schemaNamed(String name); + Schema getSchemaNamed(String name); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Sequence.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Sequence.java index bd024a03a6..f4ccaa78f9 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Sequence.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Sequence.java @@ -20,11 +20,13 @@ package org.eclipse.jpt.db; * * This interface is not intended to be implemented by clients. */ -public interface Sequence extends Comparable<Sequence> { +public interface Sequence + extends DatabaseObject, Comparable<Sequence> +{ /** - * Return the sequence's name. + * Return the sequence's schema. */ - String getName(); + Schema getSchema(); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Table.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Table.java index 2273973de3..4ea223d068 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Table.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/Table.java @@ -22,12 +22,17 @@ import java.util.Iterator; * * This interface is not intended to be implemented by clients. */ -public interface Table extends Comparable<Table> { +public interface Table + extends DatabaseObject, Comparable<Table> +{ /** - * Return the table's name. + * Return the table's schema. */ - String getName(); + Schema getSchema(); + + + // ********** columns ********** /** * Return the table's columns. @@ -45,16 +50,14 @@ public interface Table extends Comparable<Table> { Iterator<String> columnNames(); /** - * Return whether the table contains a column with the specified name, - * respecting the database's case-sensitivity. + * Return the column with specified name. The name should be an SQL + * identifier (i.e. quoted when case-sensitive, unquoted when + * case-insensitive). */ - boolean containsColumnNamed(String name); + Column getColumnNamed(String name); - /** - * Return the column in the table with the specified name, - * respecting the database's case-sensitivity. - */ - Column columnNamed(String name); + + // ********** primary key columns ********** /** * Return the table's primary key columns. @@ -62,21 +65,18 @@ public interface Table extends Comparable<Table> { Iterator<Column> primaryKeyColumns(); /** - * Return the table's single primary key column. Throw an - * IllegalStateException if the table has more than one primary key column. - */ - Column primaryKeyColumn(); - - /** * Return the number of primary key columns the table contains. */ int primaryKeyColumnsSize(); /** - * Return whether the specified column is one of the table's primary key - * columns. + * Return the table's single primary key column. Throw an + * IllegalStateException if the table has more than one primary key column. */ - boolean primaryKeyColumnsContains(Column column); + Column getPrimaryKeyColumn(); + + + // ********** foreign keys ********** /** * Return the table's foreign keys. @@ -88,28 +88,35 @@ public interface Table extends Comparable<Table> { */ int foreignKeysSize(); + + // ********** join table support ********** + /** - * Return whether the specified column is a "base" column - * for any of the table's foreign keys. + * Return whether the table is possibly a "join" table + * (i.e. it contains only 2 foreign keys). Whether the table *actually* is + * a "join" table is determined by the semantics of the database design. */ - boolean foreignKeyBaseColumnsContains(Column column); + boolean isPossibleJoinTable(); /** - * Return the table's name, converted to a Java-appropriate class - * identifier, respecting the database's case-sensitivity. + * Assuming the table is a "join" table, return the foreign key to the + * "owning" table. + * @see #isPossibleJoinTable() */ - String getShortJavaClassName(); + ForeignKey getJoinTableOwningForeignKey(); /** - * Return whether the table's name matches the specified Java-appropriate - * identifier, respecting the database's case-sensitivity. + * Assuming the table is a "join" table, return the foreign key to the + * "non-owning" table. + * @see #isPossibleJoinTable() */ - boolean matchesShortJavaClassName(String shortJavaClassName); + ForeignKey getJoinTableNonOwningForeignKey(); /** - * Return the table's name, converted to a Java-appropriate field - * identifier, respecting the database's case-sensitivity. + * Assuming the table is a "join" table, return whether its name matches + * the JPA default (i.e. "OWNINGTABLE_NONOWNINGTABLE"). + * @see #isPossibleJoinTable() */ - public String getJavaFieldName(); + boolean joinTableNameIsDefault(); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPCatalogWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPCatalogWrapper.java index 1319675ade..63414ca0f9 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPCatalogWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPCatalogWrapper.java @@ -21,9 +21,6 @@ final class DTPCatalogWrapper extends DTPSchemaContainerWrapper implements Catalog { - // backpointer to parent - private final DTPDatabaseWrapper database; - // the wrapped DTP catalog private final org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog; @@ -32,7 +29,6 @@ final class DTPCatalogWrapper DTPCatalogWrapper(DTPDatabaseWrapper database, org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog) { super(database, dtpCatalog); - this.database = database; this.dtpCatalog = dtpCatalog; } @@ -40,43 +36,54 @@ final class DTPCatalogWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - super.catalogObjectChanged(eventType); - this.getConnectionProfile().catalogChanged(this, eventType); - } - - - // ********** Catalog implementation ********** - - @Override - public String getName() { - return this.dtpCatalog.getName(); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().catalogChanged(this); } - // ***** schemata + // ********** DTPSchemaContainerWrapper implementation ********** @Override @SuppressWarnings("unchecked") - List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata() { + List<org.eclipse.datatools.modelbase.sql.schema.Schema> getDTPSchemata() { return this.dtpCatalog.getSchemas(); } + @Override + DTPCatalogWrapper getCatalog() { + return this; + } - // ********** internal methods ********** - - boolean wraps(org.eclipse.datatools.modelbase.sql.schema.Catalog catalog) { - return this.dtpCatalog == catalog; + @Override + DTPSchemaWrapper getSchema(org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema) { + return this.wraps(dtpSchema.getCatalog()) ? + this.getSchema_(dtpSchema) + : + this.getDatabase().getSchema(dtpSchema); } @Override - boolean isCaseSensitive() { - return this.database.isCaseSensitive(); + DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { + return this.wraps(dtpTable.getSchema().getCatalog()) ? + this.getTable_(dtpTable) + : + this.getDatabase().getTable(dtpTable); } @Override - DTPDatabaseWrapper database() { - return this.database; + DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + return this.wraps(dtpColumn.getTable().getSchema().getCatalog()) ? + this.getColumn_(dtpColumn) + : + this.getDatabase().getColumn(dtpColumn); + } + + + // ********** DatabaseObject implementation ********** + + public String getName() { + return this.dtpCatalog.getName(); } @@ -86,4 +93,11 @@ final class DTPCatalogWrapper return Collator.getInstance().compare(this.getName(), catalog.getName()); } + + // ********** internal methods ********** + + boolean wraps(org.eclipse.datatools.modelbase.sql.schema.Catalog catalog) { + return this.dtpCatalog == catalog; + } + } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPColumnWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPColumnWrapper.java index 2c32477588..709d8d1736 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPColumnWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPColumnWrapper.java @@ -18,47 +18,23 @@ import org.eclipse.datatools.modelbase.sql.datatypes.PrimitiveType; import org.eclipse.jpt.db.Column; import org.eclipse.jpt.utility.JavaType; import org.eclipse.jpt.utility.internal.ClassTools; -import org.eclipse.jpt.utility.internal.NameTools; import org.eclipse.jpt.utility.internal.SimpleJavaType; /** * Wrap a DTP Column */ final class DTPColumnWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements Column { - // backpointer to parent - private final DTPTableWrapper table; - // the wrapped DTP column private final org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn; - // ***** some constants used when converting the column to a Java field - // TODO Object is the default? - private static final JavaType DEFAULT_JAVA_TYPE = new SimpleJavaType(java.lang.Object.class); - - private static final JavaType BLOB_JAVA_TYPE = new SimpleJavaType(java.sql.Blob.class); - private static final JavaType BYTE_ARRAY_JAVA_TYPE = new SimpleJavaType(byte[].class); - - private static final JavaType CLOB_JAVA_TYPE = new SimpleJavaType(java.sql.Clob.class); - private static final JavaType STRING_JAVA_TYPE = new SimpleJavaType(java.lang.String.class); - - private static final JavaType UTIL_DATE_JAVA_TYPE = new SimpleJavaType(java.util.Date.class); - private static final JavaType SQL_DATE_JAVA_TYPE = new SimpleJavaType(java.sql.Date.class); - private static final JavaType SQL_TIME_JAVA_TYPE = new SimpleJavaType(java.sql.Time.class); - private static final JavaType SQL_TIMESTAMP_JAVA_TYPE = new SimpleJavaType(java.sql.Timestamp.class); - - private static final JavaType BIG_DECIMAL_JAVA_TYPE = new SimpleJavaType(java.math.BigDecimal.class); - private static final JavaType LONG_JAVA_TYPE = new SimpleJavaType(long.class); - - // ********** constructor ********** DTPColumnWrapper(DTPTableWrapper table, org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { super(table, dtpColumn); - this.table = table; this.dtpColumn = dtpColumn; } @@ -66,36 +42,45 @@ final class DTPColumnWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - this.getConnectionProfile().columnChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().columnChanged(this); } // ********** Column implementation ********** - @Override public String getName() { return this.dtpColumn.getName(); } + public DTPTableWrapper getTable() { + return (DTPTableWrapper) this.getParent(); + } + + public boolean isPrimaryKeyColumn() { + return this.getTable().primaryKeyColumnsContains(this); + } + + public boolean isForeignKeyColumn() { + return this.getTable().foreignKeyBaseColumnsContains(this); + } + public String getDataTypeName() { DataType dataType = this.dtpColumn.getDataType(); return (dataType == null) ? null : dataType.getName(); } - public String getJavaFieldName() { - String jName = this.getName(); - if ( ! this.isCaseSensitive()) { - jName = jName.toLowerCase(); - } - return NameTools.convertToJavaIdentifier(jName); + public String getJavaTypeDeclaration() { + return this.getJavaType().declaration(); } - public boolean matchesJavaFieldName(String javaFieldName) { - return this.isCaseSensitive() ? - this.getName().equals(javaFieldName) + public JavaType getJavaType() { + DataType dataType = this.dtpColumn.getDataType(); + return (dataType instanceof PredefinedDataType) ? + convertToJPAJavaType(this.getJavaType((PredefinedDataType) dataType)) : - this.getName().equalsIgnoreCase(javaFieldName); + DEFAULT_JAVA_TYPE; } public String getPrimaryKeyJavaTypeDeclaration() { @@ -103,7 +88,61 @@ final class DTPColumnWrapper } public JavaType getPrimaryKeyJavaType() { - return this.jpaSpecCompliantPrimaryKeyJavaType(this.getJavaType()); + return convertToJPAPrimaryKeyJavaType(this.getJavaType()); + } + + private JavaType getJavaType(PredefinedDataType dataType) { + // this is just a bit hacky: moving from a type declaration to a class name to a type declaration... + String dtpJavaClassName = this.getDefinition(dataType).getJavaClassName(); + return new SimpleJavaType(ClassTools.classNameForTypeDeclaration(dtpJavaClassName)); + } + + private PredefinedDataTypeDefinition getDefinition(PredefinedDataType dataType) { + return this.getDatabase().getDTPDefinition().getPredefinedDataTypeDefinition(dataType.getName()); + } + + public boolean dataTypeIsLOB() { + DataType dataType = this.dtpColumn.getDataType(); + return (dataType instanceof PredefinedDataType) ? + primitiveTypeIsLob(((PredefinedDataType) dataType).getPrimitiveType()) + : + false; + } + + + // ********** Comparable implementation ********** + + public int compareTo(Column column) { + return Collator.getInstance().compare(this.getName(), column.getName()); + } + + + // ********** internal methods ********** + + boolean wraps(org.eclipse.datatools.modelbase.sql.tables.Column column) { + return this.dtpColumn == column; + } + + @Override + void clear() { + // no state to clear + } + + + // ********** static methods ********** + + /** + * The JDBC spec says JDBC drivers should be able to map BLOBs and CLOBs + * directly, but the JPA spec does not allow them. + */ + private static JavaType convertToJPAJavaType(JavaType javaType) { + if (javaType.equals(BLOB_JAVA_TYPE)) { + return BYTE_ARRAY_JAVA_TYPE; + } + if (javaType.equals(CLOB_JAVA_TYPE)) { + return STRING_JAVA_TYPE; + } + return javaType; } /** @@ -115,7 +154,7 @@ final class DTPColumnWrapper * java.util.Date * java.sql.Date */ - private JavaType jpaSpecCompliantPrimaryKeyJavaType(JavaType javaType) { + private static JavaType convertToJPAPrimaryKeyJavaType(JavaType javaType) { if (javaType.isVariablePrimitive() || javaType.isVariablePrimitiveWrapper() || javaType.equals(STRING_JAVA_TYPE) @@ -136,76 +175,29 @@ final class DTPColumnWrapper return STRING_JAVA_TYPE; } - public String getJavaTypeDeclaration() { - return this.getJavaType().declaration(); - } - - public JavaType getJavaType() { - DataType dataType = this.dtpColumn.getDataType(); - return (dataType instanceof PredefinedDataType) ? - this.jpaSpecCompliantJavaType(this.javaType((PredefinedDataType) dataType)) - : - DEFAULT_JAVA_TYPE; - } - - private JavaType javaType(PredefinedDataType dataType) { - // this is just a bit hacky: moving from a type declaration to a class name to a type declaration... - String dtpJavaClassName = this.predefinedDataTypeDefinition(dataType).getJavaClassName(); - return new SimpleJavaType(ClassTools.classNameForTypeDeclaration(dtpJavaClassName)); - } - - private PredefinedDataTypeDefinition predefinedDataTypeDefinition(PredefinedDataType dataType) { - return this.database().getDtpDefinition().getPredefinedDataTypeDefinition(dataType.getName()); - } - - /** - * The JDBC spec says JDBC drivers should be able to map BLOBs and CLOBs - * directly, but the JPA spec does not allow them. - */ - private JavaType jpaSpecCompliantJavaType(JavaType javaType) { - if (javaType.equals(BLOB_JAVA_TYPE)) { - return BYTE_ARRAY_JAVA_TYPE; - } - if (javaType.equals(CLOB_JAVA_TYPE)) { - return STRING_JAVA_TYPE; - } - return javaType; - } - - public boolean dataTypeIsLOB() { - DataType dataType = this.dtpColumn.getDataType(); - return (dataType instanceof PredefinedDataType) ? - this.primitiveTypeIsLob(((PredefinedDataType) dataType).getPrimitiveType()) - : - false; - } - - private boolean primitiveTypeIsLob(PrimitiveType primitiveType) { + private static boolean primitiveTypeIsLob(PrimitiveType primitiveType) { return (primitiveType == PrimitiveType.BINARY_LARGE_OBJECT_LITERAL) || (primitiveType == PrimitiveType.CHARACTER_LARGE_OBJECT_LITERAL) || (primitiveType == PrimitiveType.NATIONAL_CHARACTER_LARGE_OBJECT_LITERAL); } - // ********** Comparable implementation ********** - - public int compareTo(Column column) { - return Collator.getInstance().compare(this.getName(), column.getName()); - } - + // ***** some constants used when converting the column to a Java attribute + // TODO Object is the default? + private static final JavaType DEFAULT_JAVA_TYPE = new SimpleJavaType(java.lang.Object.class); - // ********** internal methods ********** + private static final JavaType BLOB_JAVA_TYPE = new SimpleJavaType(java.sql.Blob.class); + private static final JavaType BYTE_ARRAY_JAVA_TYPE = new SimpleJavaType(byte[].class); - boolean wraps(org.eclipse.datatools.modelbase.sql.tables.Column column) { - return this.dtpColumn == column; - } + private static final JavaType CLOB_JAVA_TYPE = new SimpleJavaType(java.sql.Clob.class); + private static final JavaType STRING_JAVA_TYPE = new SimpleJavaType(java.lang.String.class); - boolean isCaseSensitive() { - return this.table.isCaseSensitive(); - } + private static final JavaType UTIL_DATE_JAVA_TYPE = new SimpleJavaType(java.util.Date.class); + private static final JavaType SQL_DATE_JAVA_TYPE = new SimpleJavaType(java.sql.Date.class); + private static final JavaType SQL_TIME_JAVA_TYPE = new SimpleJavaType(java.sql.Time.class); + private static final JavaType SQL_TIMESTAMP_JAVA_TYPE = new SimpleJavaType(java.sql.Timestamp.class); - DTPDatabaseWrapper database() { - return this.table.database(); - } + private static final JavaType BIG_DECIMAL_JAVA_TYPE = new SimpleJavaType(java.math.BigDecimal.class); + private static final JavaType LONG_JAVA_TYPE = new SimpleJavaType(long.class); } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileFactory.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileFactory.java new file mode 100644 index 0000000000..c128831dd5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileFactory.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package org.eclipse.jpt.db.internal; + +import java.util.Iterator; +import java.util.Vector; + +import org.eclipse.datatools.connectivity.IConnectionProfile; +import org.eclipse.datatools.connectivity.IProfileListener1; +import org.eclipse.datatools.connectivity.ProfileManager; +import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.ConnectionProfileFactory; +import org.eclipse.jpt.db.ConnectionProfileListener; +import org.eclipse.jpt.db.DatabaseFinder; +import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; + +/** + * Wrap the DTP ProfileManager in yet another singleton. + */ +public final class DTPConnectionProfileFactory + implements ConnectionProfileFactory +{ + private ProfileManager dtpProfileManager; + + private LocalProfileListener profileListener; + + + // ********** singleton ********** + + private static final DTPConnectionProfileFactory INSTANCE = new DTPConnectionProfileFactory(); + + public static DTPConnectionProfileFactory instance() { + return INSTANCE; + } + + /** + * 'private' to ensure singleton + */ + private DTPConnectionProfileFactory() { + super(); + } + + + // ********** lifecycle ********** + + /** + * called by plug-in + */ + public synchronized void start() { + this.dtpProfileManager = ProfileManager.getInstance(); + this.profileListener = new LocalProfileListener(); + this.dtpProfileManager.addProfileListener(this.profileListener); + } + + /** + * called by plug-in + */ + public synchronized void stop() { + this.dtpProfileManager.removeProfileListener(this.profileListener); + this.profileListener = null; + this.dtpProfileManager = null; + } + + + // ********** connection profiles ********** + + public ConnectionProfile buildConnectionProfile(String name, DatabaseFinder finder) { + for (IConnectionProfile dtpProfile : this.dtpProfileManager.getProfiles()) { + if (dtpProfile.getName().equals(name)) { + return new DTPConnectionProfileWrapper(dtpProfile, finder); + } + } + return null; + } + + public ConnectionProfile buildConnectionProfile(String name) { + return this.buildConnectionProfile(name, DatabaseFinder.Simple.instance()); + } + + public Iterator<String> connectionProfileNames() { + return new TransformationIterator<IConnectionProfile, String>(this.dtpConnectionProfiles()) { + @Override + protected String transform(IConnectionProfile dtpProfile) { + return dtpProfile.getName(); + } + }; + } + + private Iterator<IConnectionProfile> dtpConnectionProfiles() { + return new ArrayIterator<IConnectionProfile>(this.dtpProfileManager.getProfiles()); + } + + + // ********** listeners ********** + + public void addConnectionProfileListener(ConnectionProfileListener listener) { + this.profileListener.addConnectionProfileListener(listener); + } + + public void removeConnectionProfileListener(ConnectionProfileListener listener) { + this.profileListener.removeConnectionProfileListener(listener); + } + + + // ********** listener ********** + + /** + * Forward events to the factory's listeners. + */ + private class LocalProfileListener implements IProfileListener1 { + private Vector<ConnectionProfileListener> listeners = new Vector<ConnectionProfileListener>(); + + LocalProfileListener() { + super(); + } + + void addConnectionProfileListener(ConnectionProfileListener listener) { + this.listeners.add(listener); + } + + void removeConnectionProfileListener(ConnectionProfileListener listener) { + this.listeners.remove(listener); + } + + private Iterator<ConnectionProfileListener> listeners() { + return new CloneIterator<ConnectionProfileListener>(this.listeners); + } + + // ********** IProfileListener implementation ********** + + public void profileAdded(IConnectionProfile dtpProfile) { + String name = dtpProfile.getName(); + for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().connectionProfileAdded(name); + } + } + + public void profileChanged(IConnectionProfile dtpProfile, String oldName, String oldDescription, Boolean oldAutoConnect) { + String newName = dtpProfile.getName(); + if ( ! newName.equals(oldName)) { + for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().connectionProfileRenamed(oldName, newName); + } + } + } + + public void profileChanged(IConnectionProfile dtpProfile) { + // this method shouldn't be called on IProfileListener1 + throw new UnsupportedOperationException(); + } + + public void profileDeleted(IConnectionProfile dtpProfile) { + String name = dtpProfile.getName(); + for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().connectionProfileRemoved(name); + } + } + + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileRepository.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileRepository.java deleted file mode 100644 index 694ae57176..0000000000 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileRepository.java +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.db.internal; - -import java.util.Iterator; -import java.util.Vector; - -import org.eclipse.datatools.connectivity.IConnectionProfile; -import org.eclipse.datatools.connectivity.IProfileListener; -import org.eclipse.datatools.connectivity.ProfileManager; -import org.eclipse.jpt.db.ConnectionProfile; -import org.eclipse.jpt.db.ConnectionProfileRepository; -import org.eclipse.jpt.db.ConnectionProfileListener; -import org.eclipse.jpt.utility.internal.ClassTools; -import org.eclipse.jpt.utility.internal.iterators.CloneIterator; -import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; - -/** - * Wrap the DTP ProfileManager. - */ -public final class DTPConnectionProfileRepository - implements ConnectionProfileRepository -{ - private ProfileManager dtpProfileManager; - - private LocalProfileListener profileListener; - - private final Vector<DTPConnectionProfileWrapper> connectionProfiles = new Vector<DTPConnectionProfileWrapper>(); - - - // ********** singleton ********** - - private static final DTPConnectionProfileRepository INSTANCE = new DTPConnectionProfileRepository(); - - public static DTPConnectionProfileRepository instance() { - return INSTANCE; - } - - /** - * 'private' to ensure singleton - */ - private DTPConnectionProfileRepository() { - super(); - } - - - // ********** lifecycle ********** - - /** - * called by plug-in - */ - public synchronized void start() { - this.dtpProfileManager = ProfileManager.getInstance(); - this.profileListener = new LocalProfileListener(); - this.dtpProfileManager.addProfileListener(this.profileListener); - for (IConnectionProfile dtpProfile : this.dtpProfileManager.getProfiles()) { - this.connectionProfiles.add(new DTPConnectionProfileWrapper(dtpProfile)); - } - } - - /** - * called by plug-in - */ - public synchronized void stop() { - for (DTPConnectionProfileWrapper profile : this.connectionProfiles) { - profile.dispose(); - } - this.connectionProfiles.clear(); - this.dtpProfileManager.removeProfileListener(this.profileListener); - this.profileListener = null; - this.dtpProfileManager = null; - } - - - // ********** profiles ********** - - public synchronized Iterator<ConnectionProfile> connectionProfiles() { - return new CloneIterator<ConnectionProfile>(this.connectionProfiles); // read-only - } - - private synchronized Iterator<DTPConnectionProfileWrapper> connectionProfileWrappers() { - return new CloneIterator<DTPConnectionProfileWrapper>(this.connectionProfiles); // read-only - } - - public int connectionProfilesSize() { - return this.connectionProfiles.size(); - } - - public Iterator<String> connectionProfileNames() { - return new TransformationIterator<DTPConnectionProfileWrapper, String>(this.connectionProfileWrappers()) { - @Override - protected String transform(DTPConnectionProfileWrapper profile) { - return profile.getName(); - } - }; - } - - public boolean containsConnectionProfileNamed(String name) { - return ! this.connectionProfileNamed(name).isNull(); - } - - public ConnectionProfile connectionProfileNamed(String name) { - for (Iterator<DTPConnectionProfileWrapper> stream = this.connectionProfileWrappers(); stream.hasNext(); ) { - DTPConnectionProfileWrapper profile = stream.next(); - if (profile.getName().equals(name)) { - return profile; - } - } - return NullConnectionProfile.instance(); - } - - synchronized DTPConnectionProfileWrapper addConnectionProfile(IConnectionProfile dtpConnectionProfile) { - for (DTPConnectionProfileWrapper wrapper : this.connectionProfiles) { - if (wrapper.wraps(dtpConnectionProfile)) { - throw new IllegalStateException("duplicate connection profile: " + dtpConnectionProfile.getName()); //$NON-NLS-1$ - } - } - DTPConnectionProfileWrapper wrapper = new DTPConnectionProfileWrapper(dtpConnectionProfile); - this.connectionProfiles.add(wrapper); - return wrapper; - } - - synchronized DTPConnectionProfileWrapper removeConnectionProfile(IConnectionProfile dtpConnectionProfile) { - for (Iterator<DTPConnectionProfileWrapper> stream = this.connectionProfiles.iterator(); stream.hasNext(); ) { - DTPConnectionProfileWrapper wrapper = stream.next(); - if (wrapper.wraps(dtpConnectionProfile)) { - stream.remove(); - return wrapper; - } - } - throw new IllegalStateException("invalid connection profile: " + dtpConnectionProfile.getName()); //$NON-NLS-1$ - } - - synchronized DTPConnectionProfileWrapper connectionProfile(IConnectionProfile dtpConnectionProfile) { - for (DTPConnectionProfileWrapper wrapper : this.connectionProfiles) { - if (wrapper.wraps(dtpConnectionProfile)) { - return wrapper; - } - } - throw new IllegalStateException("invalid connection profile: " + dtpConnectionProfile.getName()); //$NON-NLS-1$ - } - - - // ********** Object overrides ********** - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(ClassTools.toStringClassNameForObject(this)); - sb.append((this.connectionProfiles != null) ? this.connectionProfiles : "<'connectionProfiles' uninitialized>"); //$NON-NLS-1$ - return sb.toString(); - } - - - // ********** listeners ********** - - public void addConnectionProfileListener(ConnectionProfileListener listener) { - this.profileListener.addConnectionProfileListener(listener); - } - - public void removeConnectionProfileListener(ConnectionProfileListener listener) { - this.profileListener.removeConnectionProfileListener(listener); - } - - - // ********** listener ********** - - /** - * Keep the repository in synch with the DTP profile manager - * and forward events to the repository's listeners. - */ - private class LocalProfileListener implements IProfileListener { - private Vector<ConnectionProfileListener> listeners = new Vector<ConnectionProfileListener>(); - - LocalProfileListener() { - super(); - } - - void addConnectionProfileListener(ConnectionProfileListener listener) { - this.listeners.add(listener); - } - - void removeConnectionProfileListener(ConnectionProfileListener listener) { - this.listeners.remove(listener); - } - - private Iterator<ConnectionProfileListener> listeners() { - return new CloneIterator<ConnectionProfileListener>(this.listeners); - } - - // ********** IProfileListener implementation ********** - - public void profileAdded(IConnectionProfile dtpProfile) { - // synch the repository then notify listeners - DTPConnectionProfileWrapper profile = DTPConnectionProfileRepository.this.addConnectionProfile(dtpProfile); - for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { - stream.next().connectionProfileReplaced(NullConnectionProfile.instance(), profile); - } - } - - public void profileChanged(IConnectionProfile dtpProfile) { - DTPConnectionProfileWrapper profile = DTPConnectionProfileRepository.this.connectionProfile(dtpProfile); - for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { - stream.next().connectionProfileChanged(profile); - } - } - - public void profileDeleted(IConnectionProfile dtpProfile) { - // synch the repository then notify listeners - DTPConnectionProfileWrapper profile = DTPConnectionProfileRepository.this.removeConnectionProfile(dtpProfile); - for (Iterator<ConnectionProfileListener> stream = this.listeners(); stream.hasNext(); ) { - stream.next().connectionProfileReplaced(profile, NullConnectionProfile.instance()); - } - } - - } - -} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileWrapper.java index 742f3447ef..97b8d980ae 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPConnectionProfileWrapper.java @@ -25,7 +25,8 @@ import org.eclipse.datatools.sqltools.core.DatabaseIdentifier; import org.eclipse.datatools.sqltools.core.profile.ProfileUtil; import org.eclipse.jpt.db.ConnectionListener; import org.eclipse.jpt.db.ConnectionProfile; -import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.DatabaseFinder; +import org.eclipse.jpt.db.DatabaseObject; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.CloneIterator; @@ -33,42 +34,47 @@ import org.eclipse.jpt.utility.internal.iterators.CloneIterator; * Wrap a DTP ConnectionProfile */ final class DTPConnectionProfileWrapper - implements ConnectionProfile, ConnectionProfileHolder + implements DTPDatabaseObject, ConnectionProfile { // the wrapped DTP connection profile private final IConnectionProfile dtpConnectionProfile; + // finder supplied by the JPA platform (determines case-sensitivity, etc.) + private final DatabaseFinder finder; + + // callback passed to the finder + private final DatabaseFinder.DefaultCallback databaseFinderCallback; + // the DTP managed connection we listen to private final IManagedConnection dtpManagedConnection; - // forward events from the DTP connection profile's managed connections + // forward events from the DTP managed connection above; + // we listen and propagate events iff we have listeners ourselves private final LocalConnectionListener connectionListener; - // lazy-initialized - can be a "null" database - private InternalDatabase database; + // lazy-initialized, and deleted at disconnect + private DTPDatabaseWrapper database; // ********** constants ********** - public static final String LIVE_DTP_CONNECTION_TYPE = "java.sql.Connection"; //$NON-NLS-1$ - - public static final String OFFLINE_DTP_CONNECTION_TYPE = ConnectionInfo.class.getName(); + private static final String LIVE_DTP_CONNECTION_TYPE = "java.sql.Connection"; //$NON-NLS-1$ - public static final String DATABASE_PRODUCT_PROP_ID = "org.eclipse.datatools.connectivity.server.version"; //$NON-NLS-1$ + private static final String OFFLINE_DTP_CONNECTION_TYPE = ConnectionInfo.class.getName(); - public static final String POSTGRESQL_VENDOR = "postgres"; //$NON-NLS-1$ - - public static final String POSTGRESQL_DEFAULT_SCHEMA_NAME = "public"; //$NON-NLS-1$ + private static final String DATABASE_PRODUCT_PROP_ID = "org.eclipse.datatools.connectivity.server.version"; //$NON-NLS-1$ // ********** constructor ********** - DTPConnectionProfileWrapper(IConnectionProfile dtpConnectionProfile) { + DTPConnectionProfileWrapper(IConnectionProfile dtpConnectionProfile, DatabaseFinder finder) { super(); this.dtpConnectionProfile = dtpConnectionProfile; + this.finder = finder; + this.databaseFinderCallback = new DatabaseFinderCallback(); this.dtpManagedConnection = this.buildDTPManagedConnection(); this.connectionListener = new LocalConnectionListener(); - this.dtpManagedConnection.addConnectionListener(this.connectionListener); + // don't listen to the managed connection yet } private IManagedConnection buildDTPManagedConnection() { @@ -78,72 +84,46 @@ final class DTPConnectionProfileWrapper } - // ********** ConnectionProfileHolder implementation ********** - - public DTPConnectionProfileWrapper getConnectionProfile() { - return this; - } - - - // ********** ConnectionProfile implementation ********** + // ********** DatabaseObject implementation ********** public String getName() { return this.dtpConnectionProfile.getName(); } - public boolean isNull() { - return false; + public String getAnnotationIdentifier(String javaIdentifier) { + // connection profiles should not be in Java annotations + throw new UnsupportedOperationException(); } - public void connect() { - if (this.isDisconnected()) { - this.checkStatus(this.dtpConnectionProfile.connect()); - } - } - - public void disconnect() { - this.checkStatus(this.dtpConnectionProfile.disconnect()); + public String getAnnotationIdentifier() { + // connection profiles should not be in Java annotations + throw new UnsupportedOperationException(); } - public boolean isActive() { - return this.isConnected() || this.isWorkingOffline(); - } - public boolean isInactive() { - return ! this.isActive(); - } + // ********** DTPDatabaseObject implementation ********** - public boolean isConnected() { - return this.dtpManagedConnection.isConnected() - && ! this.dtpManagedConnection.isWorkingOffline(); + public DTPConnectionProfileWrapper getConnectionProfile() { + return this; } - public boolean isDisconnected() { - return ! this.isConnected(); + public synchronized DTPDatabaseWrapper getDatabase() { + if (this.database == null) { + this.database = this.buildDatabase(); + } + return this.database; } - public boolean isWorkingOffline() { - return this.dtpManagedConnection.isWorkingOffline(); - } - public boolean supportsWorkOfflineMode() { - return this.dtpConnectionProfile.supportsWorkOfflineMode(); - } + // ********** ConnectionProfile implementation ********** - public boolean canWorkOffline() { - return this.dtpConnectionProfile.canWorkOffline(); + // ***** properties + public String getProviderID() { + return this.dtpConnectionProfile.getProviderId(); } - public IStatus saveWorkOfflineData() { - return this.dtpConnectionProfile.saveWorkOfflineData(); - } - - public IStatus workOffline() { - return this.dtpConnectionProfile.workOffline(); - } - - public String getDatabaseVendor() { - return this.getProperty(IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID); + public String getInstanceID() { + return this.dtpConnectionProfile.getInstanceID(); } public String getDatabaseName() { @@ -154,67 +134,129 @@ final class DTPConnectionProfileWrapper return this.getProperty(DATABASE_PRODUCT_PROP_ID); } + public String getDatabaseVendor() { + return this.getProperty(IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID); + } + public String getDatabaseVersion() { return this.getProperty(IJDBCDriverDefinitionConstants.DATABASE_VERSION_PROP_ID); } + public String getDriverClassName() { + return this.getProperty(IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID); + } + + public String getURL() { + return this.getProperty(IJDBCDriverDefinitionConstants.URL_PROP_ID); + } + public String getUserName() { String userName = this.getProperty(IJDBCDriverDefinitionConstants.USERNAME_PROP_ID); - if (userName.contains(" ")){ - return userName.split("\\s")[0]; - } - return userName; + // 208946 handle username like "sys as sysdba" on Oracle + int index = userName.indexOf(' '); + return (index == -1) ? userName : userName.substring(0, index); } public String getUserPassword() { return this.getProperty(IJDBCDriverDefinitionConstants.PASSWORD_PROP_ID); } - public synchronized InternalDatabase getDatabase() { - if (this.database == null) { - this.database = this.buildDatabase(); - } - return this.database; + public String getDriverDefinitionID() { + return this.getProperty(DRIVER_DEFINITION_PROP_ID); } - public DTPCatalogWrapper getDefaultCatalog() { - return this.getDatabase().getDefaultCatalog(); + public String getDriverJarList() { + return DriverManager.getInstance().getDriverInstanceByID(this.getDriverDefinitionID()).getJarList(); } - public void addConnectionListener(ConnectionListener listener) { - this.connectionListener.addConnectionListener(listener); + // ***** connection + public boolean isActive() { + return this.isConnected() || this.isWorkingOffline(); } - public void removeConnectionListener(ConnectionListener listener) { - this.connectionListener.removeConnectionListener(listener); + public boolean isInactive() { + return ! this.isActive(); } - public Schema getDefaultSchema() { - return this.getDatabase().schemaNamed(this.getDefaultSchemaName()); + public boolean isConnected() { + return this.dtpManagedConnection.isConnected() + && ! this.dtpManagedConnection.isWorkingOffline(); } - public String getDriverClassName() { - return this.getProperty(IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID); + public boolean isDisconnected() { + return ! this.isConnected(); } - public String getUrl() { - return this.getProperty(IJDBCDriverDefinitionConstants.URL_PROP_ID); + public void connect() { + if (this.isDisconnected()) { + this.checkStatus(this.dtpConnectionProfile.connect()); + } + } + + public void disconnect() { + this.checkStatus(this.dtpConnectionProfile.disconnect()); } - public String getInstanceID() { - return this.dtpConnectionProfile.getInstanceID(); + // ***** off-line support + public boolean isWorkingOffline() { + return this.dtpManagedConnection.isWorkingOffline(); } - public String getProviderID() { - return this.dtpConnectionProfile.getProviderId(); + public boolean supportsWorkOfflineMode() { + return this.dtpConnectionProfile.supportsWorkOfflineMode(); } - public String getDriverDefinitionID() { - return this.getProperty(DRIVER_DEFINITION_PROP_ID); + public IStatus saveWorkOfflineData() { + return this.dtpConnectionProfile.saveWorkOfflineData(); + } + + public boolean canWorkOffline() { + return this.dtpConnectionProfile.canWorkOffline(); } - public String getDriverJarList() { - return DriverManager.getInstance().getDriverInstanceByID(this.getDriverDefinitionID()).getJarList(); + public IStatus workOffline() { + return this.dtpConnectionProfile.workOffline(); + } + + // ***** listeners + public synchronized void addConnectionListener(ConnectionListener listener) { + if (this.hasNoListeners()) { // first listener added + this.startListening(); + } + this.connectionListener.addConnectionListener(listener); + } + + private void startListening() { + this.dtpManagedConnection.addConnectionListener(this.connectionListener); + if (this.database != null) { // don't trigger database creation + if (this.isConnected()) { // DTP does not change when off-line + this.database.startListening(); + } + } + } + + public synchronized void removeConnectionListener(ConnectionListener listener) { + this.connectionListener.removeConnectionListener(listener); + if (this.hasNoListeners()) { // last listener removed + this.stopListening(); + } + } + + private void stopListening() { + if (this.database != null) { // don't trigger database creation + if (this.isConnected()) { // DTP does not change when off-line + this.database.stopListening(); + } + } + this.dtpManagedConnection.removeConnectionListener(this.connectionListener); + } + + boolean hasNoListeners() { + return this.connectionListener.hasNoListeners(); + } + + boolean hasAnyListeners() { + return this.connectionListener.hasAnyListeners(); } @@ -225,14 +267,16 @@ final class DTPConnectionProfileWrapper return; } if (status.isMultiStatus()) { - status = status.getChildren()[0]; // take the first one? + for (IStatus child : status.getChildren()) { + this.checkStatus(child); // recurse, looking for the first error + } } throw new RuntimeException(status.getMessage(), status.getException()); } - private InternalDatabase buildDatabase() { + private DTPDatabaseWrapper buildDatabase() { if (this.isInactive()) { - return NullDatabase.instance(); + return null; } if (this.isWorkingOffline()) { @@ -248,66 +292,65 @@ final class DTPConnectionProfileWrapper // so, some hackery here to handle hackery there return new DTPDatabaseWrapper(this, ProfileUtil.getDatabase(new DatabaseIdentifier(this.getName(), this.getDatabaseName()), true)); } - - boolean wraps(IConnectionProfile dtpCP) { - return this.dtpConnectionProfile == dtpCP; - } - void databaseChanged(DTPDatabaseWrapper db, int eventType) { - this.connectionListener.databaseChanged(db, eventType); + synchronized void clearDatabase() { + if (this.database != null) { + if (this.isConnected()) { // DTP does not change when off-line + this.database.stopListening(); + } + this.database = null; + } } - void catalogChanged(DTPCatalogWrapper catalog, int eventType) { - this.connectionListener.catalogChanged(catalog, eventType); + /** + * This is called by whenever we need to find a component by name + * (e.g. Table.getColumnNamed(String)). We channel all the calls to here + * and then we delegate to the JPA platform-supplied "database finder". + */ + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name) { + return this.finder.getDatabaseObjectNamed(databaseObjects, name, this.databaseFinderCallback); } - void schemaChanged(DTPSchemaWrapper schema, int eventType) { - this.connectionListener.schemaChanged(schema, eventType); + /** + * The default "database finder" calls back to here so we can delegate to + * the database, which contains all the state necessary to properly match + * identifiers. + */ + <T extends DatabaseObject> T getDatabaseObjectNamed_(T[] databaseObjects, String name) { + // the database should not be null here - call its internal method + return this.database.getDatabaseObjectNamed_(databaseObjects, name); } - void sequenceChanged(DTPSequenceWrapper sequence, int eventType) { - this.connectionListener.sequenceChanged(sequence, eventType); + void databaseChanged(DTPDatabaseWrapper db) { + this.connectionListener.databaseChanged(db); } - void tableChanged(DTPTableWrapper table, int eventType) { - this.connectionListener.tableChanged(table, eventType); + void catalogChanged(DTPCatalogWrapper catalog) { + this.connectionListener.catalogChanged(catalog); } - void columnChanged(DTPColumnWrapper column, int eventType) { - this.connectionListener.columnChanged(column, eventType); + void schemaChanged(DTPSchemaWrapper schema) { + this.connectionListener.schemaChanged(schema); } - void foreignKeyChanged(DTPForeignKeyWrapper foreignKey, int eventType) { - this.connectionListener.foreignKeyChanged(foreignKey, eventType); + void sequenceChanged(DTPSequenceWrapper sequence) { + this.connectionListener.sequenceChanged(sequence); } - /** - * private - use #getDefaultSchema() : Schema instead - */ - private String getDefaultSchemaName() { - if (this.getDatabase().getVendor().equalsIgnoreCase(POSTGRESQL_VENDOR)) { - return POSTGRESQL_DEFAULT_SCHEMA_NAME; - } - return this.getUserName(); + void tableChanged(DTPTableWrapper table) { + this.connectionListener.tableChanged(table); } - private String getProperty(String propertyName) { - return this.dtpConnectionProfile.getBaseProperties().getProperty(propertyName); + void columnChanged(DTPColumnWrapper column) { + this.connectionListener.columnChanged(column); } - - // ********** disposal ********** - - synchronized void dispose() { - this.disposeDatabase(); - this.dtpManagedConnection.removeConnectionListener(this.connectionListener); + void foreignKeyChanged(DTPForeignKeyWrapper foreignKey) { + this.connectionListener.foreignKeyChanged(foreignKey); } - synchronized void disposeDatabase() { - if (this.database != null) { - this.database.dispose(); - this.database = null; - } + private String getProperty(String propertyName) { + return this.dtpConnectionProfile.getBaseProperties().getProperty(propertyName); } @@ -332,7 +375,7 @@ final class DTPConnectionProfileWrapper * This listener translates and forwards IManagedConnectionListener and * IManagedConnectionOfflineListener events to ConnectionListeners. */ - private class LocalConnectionListener implements IManagedConnectionOfflineListener { + class LocalConnectionListener implements IManagedConnectionOfflineListener { private Vector<ConnectionListener> listeners = new Vector<ConnectionListener>(); LocalConnectionListener() { @@ -351,12 +394,20 @@ final class DTPConnectionProfileWrapper return new CloneIterator<ConnectionListener>(this.listeners); } + boolean hasNoListeners() { + return this.listeners.isEmpty(); + } + + boolean hasAnyListeners() { + return ! this.listeners.isEmpty(); + } + // ********** IManagedConnectionListener implementation ********** + // off-line or inactive => live public void opened(ConnectEvent event) { - // clear the (possibly "null") database so it will be rebuilt with the "live" data - DTPConnectionProfileWrapper.this.disposeDatabase(); + // do not build the database here - it is built on-demand // forward event to listeners for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().opened(DTPConnectionProfileWrapper.this); @@ -393,9 +444,10 @@ final class DTPConnectionProfileWrapper } } + // live or off-line => inactive public void closed(ConnectEvent event) { // clear the database - DTPConnectionProfileWrapper.this.disposeDatabase(); + DTPConnectionProfileWrapper.this.clearDatabase(); // forward event to listeners for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().closed(DTPConnectionProfileWrapper.this); @@ -407,72 +459,72 @@ final class DTPConnectionProfileWrapper // live => off-line public boolean okToDetach(ConnectEvent event) { - // don't forward the event to listeners (?) - return true; + // convert the event to an "ok to close" event; + // we are "closing" the live connection + return this.okToClose(event); } // live => off-line public void aboutToDetach(ConnectEvent event) { - // don't forward the event; the database will be cleared and - // listeners will be notified once the "offline" connection is "opened/workingOffline" + // convert the event to a "close" event; + // we are "closing" the live connection + this.closed(event); } - // live => off-line + // inactive or live => off-line public void workingOffline(ConnectEvent event) { - // clear the (possibly null) database so it will be rebuilt with the "off-line" data - DTPConnectionProfileWrapper.this.disposeDatabase(); - // convert the event to an "open" event and forward it to listeners - for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { - stream.next().opened(DTPConnectionProfileWrapper.this); - } + // convert the event to an "open" event; + // we are "opening" the off-line connection + this.opened(event); } // off-line => live public void aboutToAttach(ConnectEvent event) { - // don't forward the event; the database will be cleared and - // listeners will be notified once the "live" connection is "opened" + // convert the event to an "close" event; + // we are "closing" the off-line connection + this.closed(event); } // ********** internal methods ********** - void databaseChanged(DTPDatabaseWrapper db, int eventType) { + void databaseChanged(DTPDatabaseWrapper db) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().databaseChanged(DTPConnectionProfileWrapper.this, db); } } - void catalogChanged(DTPCatalogWrapper catalog, int eventType) { + void catalogChanged(DTPCatalogWrapper catalog) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().catalogChanged(DTPConnectionProfileWrapper.this, catalog); } } - void schemaChanged(DTPSchemaWrapper schema, int eventType) { + void schemaChanged(DTPSchemaWrapper schema) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().schemaChanged(DTPConnectionProfileWrapper.this, schema); } } - void sequenceChanged(DTPSequenceWrapper sequence, int eventType) { + void sequenceChanged(DTPSequenceWrapper sequence) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().sequenceChanged(DTPConnectionProfileWrapper.this, sequence); } } - void tableChanged(DTPTableWrapper table, int eventType) { + void tableChanged(DTPTableWrapper table) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().tableChanged(DTPConnectionProfileWrapper.this, table); } } - void columnChanged(DTPColumnWrapper column, int eventType) { + void columnChanged(DTPColumnWrapper column) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().columnChanged(DTPConnectionProfileWrapper.this, column); } } - void foreignKeyChanged(DTPForeignKeyWrapper foreignKey, int eventType) { + void foreignKeyChanged(DTPForeignKeyWrapper foreignKey) { for (Iterator<ConnectionListener> stream = this.listeners(); stream.hasNext(); ) { stream.next().foreignKeyChanged(DTPConnectionProfileWrapper.this, foreignKey); } @@ -480,4 +532,14 @@ final class DTPConnectionProfileWrapper } + + // ********** default DatabaseFinder ********** + + class DatabaseFinderCallback implements DatabaseFinder.DefaultCallback { + public <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name) { + // call back to the internal method + return DTPConnectionProfileWrapper.this.getDatabaseObjectNamed_(databaseObjects, name); + } + } + } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/ConnectionProfileHolder.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseObject.java index f106e91b4d..c976fe4b39 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/ConnectionProfileHolder.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseObject.java @@ -9,9 +9,16 @@ ******************************************************************************/ package org.eclipse.jpt.db.internal; +import org.eclipse.jpt.db.DatabaseObject; + /** - * Provide a way for clients to access the connection profile. + * DTP database object */ -interface ConnectionProfileHolder { +public interface DTPDatabaseObject extends DatabaseObject { + + /** + * covariant override + */ DTPConnectionProfileWrapper getConnectionProfile(); + } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseObjectWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseObjectWrapper.java new file mode 100644 index 0000000000..bed57df93b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseObjectWrapper.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package org.eclipse.jpt.db.internal; + +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObjectListener; +import org.eclipse.datatools.connectivity.sqm.core.rte.RefreshManager; +import org.eclipse.jpt.db.DatabaseObject; +import org.eclipse.jpt.utility.internal.StringTools; + +/** + * DTP Catalog Object Wrapper base class + */ +abstract class DTPDatabaseObjectWrapper + implements DTPDatabaseObject +{ + // we need a way to get to the connection profile + private final DTPDatabaseObject parent; + + // listen for the "catalog object" being refreshed + private final ICatalogObjectListener catalogObjectListener; + + // listen for this DTP catalog object to refresh + final ICatalogObject catalogObject; + + + // ********** construction/initialization ********** + + DTPDatabaseObjectWrapper(DTPDatabaseObject parent, Object dtpObject) { + super(); + this.parent = parent; + if (this.getConnectionProfile().isConnected()) { + // we only listen to "live" connections (as opposed to "off-line" connections) + this.catalogObject = (ICatalogObject) dtpObject; + this.catalogObjectListener = this.buildCatalogObjectListener(); + if (this.getConnectionProfile().hasAnyListeners()) { + this.startListening(); + } + } else { + this.catalogObject = null; + this.catalogObjectListener = null; + } + } + + private ICatalogObjectListener buildCatalogObjectListener() { + return new ICatalogObjectListener() { + public void notifyChanged(ICatalogObject dmElement, int eventType) { + if (dmElement == DTPDatabaseObjectWrapper.this.catalogObject) { + // 'eventType' doesn't seem to be very useful, so drop it + DTPDatabaseObjectWrapper.this.catalogObjectChanged(); + } + } + }; + } + + // typically, notify the connection profile something has changed + void catalogObjectChanged() { + this.clear(); + } + + /** + * The DTP object has changed, clear the wrapper's state so it will be + * synchronized on-demand. + */ + abstract void clear(); + + + + // ********** queries ********** + + DTPDatabaseObject getParent() { + return this.parent; + } + + public DTPConnectionProfileWrapper getConnectionProfile() { + return this.parent.getConnectionProfile(); + } + + public DTPDatabaseWrapper getDatabase() { + return this.getConnectionProfile().getDatabase(); + } + + /** + * This is called by whenever we need to find a component by name + * (e.g. Table.getColumnNamed(String)). We channel all the calls to the + * connection profile, which then delegates to the JPA platform- + * supplied "database finder". + */ + <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name) { + return this.getConnectionProfile().getDatabaseObjectNamed(databaseObjects, name); + } + + /** + * Examples: + * Oracle etc. + * Table(FOO) vs. "Foo" => null + * Table(BAR) vs. "Foo" => "BAR" + * Table(Foo) vs. "Foo" => "\"Foo\"" + * Table(Bar) vs. "Foo" => "\"Bar\"" + * + * PostgreSQL etc. + * Table(foo) vs. "Foo" => null + * Table(bar) vs. "Foo" => "bar" + * Table(Foo) vs. "Foo" => "\"Foo\"" + * Table(Bar) vs. "Foo" => "\"Bar\"" + * + * SQL Server etc. + * Table(Foo) vs. "Foo" => null + * Table(foo) vs. "Foo" => "foo" + * Table(bar) vs. "Foo" => "bar" + * Table(Bar) vs. "Foo" => "Bar" + */ + public String getAnnotationIdentifier(String javaIdentifier) { + return this.getAnnotationIdentifier(javaIdentifier, this.getName()); + } + + String getAnnotationIdentifier(String javaIdentifier, String dbIdentifier) { + if (this.getDatabase().vendorFoldsToUppercase()) { + if (StringTools.stringIsUppercase(dbIdentifier)) { + return dbIdentifier.equalsIgnoreCase(javaIdentifier) ? null : dbIdentifier; + } + return this.getDatabase().delimitIdentifier(dbIdentifier); + } + if (this.getDatabase().vendorFoldsToLowercase()) { + if (StringTools.stringIsLowercase(dbIdentifier)) { + return dbIdentifier.equalsIgnoreCase(javaIdentifier) ? null : dbIdentifier; + } + return this.getDatabase().delimitIdentifier(dbIdentifier); + } + if (this.getDatabase().vendorDoesNotFold()) { + return dbIdentifier.equals(javaIdentifier) ? null : dbIdentifier; + } + throw new IllegalStateException("unknown vendor folding: " + this.getDatabase().getVendor()); //$NON-NLS-1$ + } + + /** + * Examples: + * Oracle etc. + * Table(FOO) => "FOO" + * Table(Foo) => "\"Foo\"" + * Table(foo) => "\"foo\"" + * + * PostgreSQL etc. + * Table(foo) => "foo" + * Table(Foo) => "\"Foo\"" + * Table(FOO) => "\"FOO\"" + * + * SQL Server etc. + * Table(Foo) => "Foo" + * Table(foo) => "foo" + * Table(FOO) => "FOO" + */ + public String getAnnotationIdentifier() { + String name = this.getName(); + if (this.getDatabase().vendorFoldsToUppercase()) { + return StringTools.stringIsUppercase(name) ? name : this.getDatabase().delimitIdentifier(name); + } + if (this.getDatabase().vendorFoldsToLowercase()) { + return StringTools.stringIsLowercase(name) ? name : this.getDatabase().delimitIdentifier(name); + } + if (this.getDatabase().vendorDoesNotFold()) { + return name; + } + throw new IllegalStateException("unknown vendor folding: " + this.getDatabase().getVendor()); //$NON-NLS-1$ + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.getName()); + } + + + // ********** listening to DTP database object ********** + + // this should only be called when the connection profile is "live" and has listeners + void startListening() { + this.checkListener(); + RefreshManager.getInstance().AddListener(this.catalogObject, this.catalogObjectListener); + } + + // this should only be called when the connection profile is "live" and has no listeners + void stopListening() { + this.checkListener(); + RefreshManager.getInstance().removeListener(this.catalogObject, this.catalogObjectListener); + } + + private void checkListener() { + if (this.catalogObjectListener == null) { + throw new IllegalStateException("the catalog listener is null"); //$NON-NLS-1$ + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseWrapper.java index 911d334423..e7da680987 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPDatabaseWrapper.java @@ -17,6 +17,7 @@ import org.eclipse.datatools.connectivity.sqm.core.definition.DatabaseDefinition import org.eclipse.datatools.connectivity.sqm.internal.core.RDBCorePlugin; import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.Database; +import org.eclipse.jpt.db.DatabaseObject; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; @@ -29,33 +30,48 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; */ final class DTPDatabaseWrapper extends DTPSchemaContainerWrapper - implements InternalDatabase + implements Database { - // backpointer to parent - private final DTPConnectionProfileWrapper connectionProfile; - // the wrapped DTP database private final org.eclipse.datatools.modelbase.sql.schema.Database dtpDatabase; // lazy-initialized private DTPCatalogWrapper[] catalogs; - // lazy-initialized + // lazy-initialized - but it can be 'null' so we use a flag private DTPCatalogWrapper defaultCatalog; private boolean defaultCatalogCalculated = false; - // TODO allow user to configure? - private boolean caseSensitive = false; - private static final DTPCatalogWrapper[] EMPTY_CATALOGS = new DTPCatalogWrapper[0]; + // ********** constants ********** + + private static final String POSTGRESQL_PUBLIC_SCHEMA_NAME = "public"; //$NON-NLS-1$ + + + // ********** vendors ********** + + static final String DERBY_VENDOR = "Derby"; //$NON-NLS-1$ + static final String HSQLDB_VENDOR = "HSQLDB"; //$NON-NLS-1$ + static final String DB2_UDB_I_SERIES_VENDOR = "DB2 UDB iSeries"; //$NON-NLS-1$ + static final String DB2_UDB_VENDOR = "DB2 UDB"; //$NON-NLS-1$ + static final String DB2_UDB_Z_SERIES_VENDOR = "DB2 UDB zSeries"; //$NON-NLS-1$ + static final String INFORMIX_VENDOR = "Informix"; //$NON-NLS-1$ + static final String SQL_SERVER_VENDOR = "SQL Server"; //$NON-NLS-1$ + static final String MYSQL_VENDOR = "MySql"; //$NON-NLS-1$ + static final String ORACLE_VENDOR = "Oracle"; //$NON-NLS-1$ + static final String POSTGRES_VENDOR = "postgres"; //$NON-NLS-1$ + static final String MAXDB_VENDOR = "MaxDB"; //$NON-NLS-1$ + static final String SYBASE_ASA_VENDOR = "Sybase_ASA"; //$NON-NLS-1$ + static final String SYBASE_ASE_VENDOR = "Sybase_ASE"; //$NON-NLS-1$ + + // ********** constructor ********** DTPDatabaseWrapper(DTPConnectionProfileWrapper connectionProfile, org.eclipse.datatools.modelbase.sql.schema.Database dtpDatabase) { super(connectionProfile, dtpDatabase); - this.connectionProfile = connectionProfile; this.dtpDatabase = dtpDatabase; } @@ -63,19 +79,55 @@ final class DTPDatabaseWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - super.catalogObjectChanged(eventType); - this.getConnectionProfile().databaseChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().databaseChanged(this); + } + + @Override + public DTPDatabaseWrapper getDatabase() { + return this; } - // ********** Database implementation ********** + // ********** DTPSchemaContainerWrapper implementation ********** + + @Override + @SuppressWarnings("unchecked") + List<org.eclipse.datatools.modelbase.sql.schema.Schema> getDTPSchemata() { + return this.dtpDatabase.getSchemas(); + } @Override + DTPCatalogWrapper getCatalog() { + return null; // catalog not supported + } + + @Override + DTPSchemaWrapper getSchema(org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema) { + return this.getSchema_(dtpSchema); + } + + @Override + DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { + return this.getTable_(dtpTable); + } + + @Override + DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + return this.getColumn_(dtpColumn); + } + + + // ********** DatabaseObject implementation ********** + public String getName() { return this.dtpDatabase.getName(); } + + // ********** Database implementation ********** + public String getVendor() { return this.dtpDatabase.getVendor(); } @@ -84,39 +136,25 @@ final class DTPDatabaseWrapper return this.dtpDatabase.getVersion(); } - public DatabaseDefinition getDtpDefinition() { - return RDBCorePlugin.getDefault().getDatabaseDefinitionRegistry().getDefinition(this.dtpDatabase); - } - - // ***** caseSensitive - + // override to make method public since it's in the Database interface @Override - public boolean isCaseSensitive() { - return this.caseSensitive; - } - - // TODO - public void setCaseSensitive(boolean caseSensitive) { - this.caseSensitive = caseSensitive; + public <T extends DatabaseObject> T getDatabaseObjectNamed(T[] databaseObjects, String name) { + return super.getDatabaseObjectNamed(databaseObjects, name); } // ***** catalogs public boolean supportsCatalogs() { // if the DTP database does not have any schemata, it must have catalogs... - List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata = this.dtpSchemata(); + List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata = this.getDTPSchemata(); return (dtpSchemata == null) || dtpSchemata.isEmpty(); } public Iterator<Catalog> catalogs() { - return new ArrayIterator<Catalog>(this.catalogs_()); + return new ArrayIterator<Catalog>(this.getCatalogs()); } - private Iterator<DTPCatalogWrapper> catalogWrappers() { - return new ArrayIterator<DTPCatalogWrapper>(this.catalogs_()); - } - - private synchronized DTPCatalogWrapper[] catalogs_() { + private synchronized DTPCatalogWrapper[] getCatalogs() { if (this.catalogs == null) { this.catalogs = this.buildCatalogs(); } @@ -124,7 +162,7 @@ final class DTPDatabaseWrapper } private DTPCatalogWrapper[] buildCatalogs() { - List<org.eclipse.datatools.modelbase.sql.schema.Catalog> dtpCatalogs = this.dtpCatalogs(); + List<org.eclipse.datatools.modelbase.sql.schema.Catalog> dtpCatalogs = this.getDTPCatalogs(); if ((dtpCatalogs == null) || dtpCatalogs.isEmpty()) { return EMPTY_CATALOGS; } @@ -137,51 +175,23 @@ final class DTPDatabaseWrapper // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.schema.Catalog> dtpCatalogs() { + private List<org.eclipse.datatools.modelbase.sql.schema.Catalog> getDTPCatalogs() { return this.dtpDatabase.getCatalogs(); } public int catalogsSize() { - return this.catalogs_().length; + return this.getCatalogs().length; } public Iterator<String> catalogNames() { - return new TransformationIterator<DTPCatalogWrapper, String>(this.catalogWrappers()) { + return new TransformationIterator<Catalog, String>(this.catalogs()) { @Override - protected String transform(DTPCatalogWrapper catalog) { + protected String transform(Catalog catalog) { return catalog.getName(); } }; } - public boolean containsCatalogNamed(String name) { - return this.catalogNamed(name) != null; - } - - public DTPCatalogWrapper catalogNamed(String name) { - return this.isCaseSensitive() ? this.catalogNamedCaseSensitive(name) : this.catalogNamedIgnoreCase(name); - } - - private DTPCatalogWrapper catalogNamedCaseSensitive(String name) { - for (Iterator<DTPCatalogWrapper> stream = this.catalogWrappers(); stream.hasNext(); ) { - DTPCatalogWrapper catalog = stream.next(); - if (catalog.getName().equals(name)) { - return catalog; - } - } - return null; - } - - private DTPCatalogWrapper catalogNamedIgnoreCase(String name) { - for (Iterator<DTPCatalogWrapper> stream = this.catalogWrappers(); stream.hasNext(); ) { - DTPCatalogWrapper catalog = stream.next(); - if (StringTools.stringsAreEqualIgnoreCase(catalog.getName(), name)) { - return catalog; - } - } - return null; - } - public synchronized DTPCatalogWrapper getDefaultCatalog() { if ( ! this.defaultCatalogCalculated) { this.defaultCatalogCalculated = true; @@ -194,16 +204,15 @@ final class DTPDatabaseWrapper if ( ! this.supportsCatalogs()) { return null; } - String userName = this.connectionProfile.getUserName(); - for (Iterator<DTPCatalogWrapper> stream = this.catalogWrappers(); stream.hasNext(); ) { - DTPCatalogWrapper catalog = stream.next(); - if (catalog.getName().length() == 0) { - return catalog; // special catalog that contains all schemata + for (DTPCatalogWrapper catalog : this.getCatalogs()) { + String catalogName = catalog.getName(); + if (catalogName.length() == 0) { + return catalog; // special catalog that contains all schemata (Derby) } - if (catalog.getName().equals(userName)) { + if (catalogName.equals(this.getConnectionProfile().getUserName())) { return catalog; // user name is default catalog } - if (catalog.getName().equals(this.getName())) { + if (catalogName.equals(this.getName())) { return catalog; // special catalog with same name as DB (PostgreSQL) } } @@ -213,9 +222,8 @@ final class DTPDatabaseWrapper /** * return the catalog for the specified DTP catalog */ - DTPCatalogWrapper catalog(org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog) { - for (Iterator<DTPCatalogWrapper> stream = this.catalogWrappers(); stream.hasNext(); ) { - DTPCatalogWrapper catalog = stream.next(); + DTPCatalogWrapper getCatalog(org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog) { + for (DTPCatalogWrapper catalog : this.getCatalogs()) { if (catalog.wraps(dtpCatalog)) { return catalog; } @@ -223,79 +231,290 @@ final class DTPDatabaseWrapper throw new IllegalArgumentException("invalid DTP catalog: " + dtpCatalog); //$NON-NLS-1$ } + public DTPCatalogWrapper getCatalogNamed(String name) { + return this.getDatabaseObjectNamed(this.getCatalogs(), name); + } + // ***** schemata @Override - @SuppressWarnings("unchecked") - List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata() { - return this.dtpDatabase.getSchemas(); + synchronized DTPSchemaWrapper[] getSchemata() { + DTPCatalogWrapper cat = this.getDefaultCatalog(); + return (cat == null) ? super.getSchemata() : cat.getSchemata(); } - @Override - synchronized DTPSchemaWrapper[] schemata_() { - return (this.supportsCatalogs()) ? - this.getDefaultCatalog().schemata_() - : - super.schemata_(); + public DTPSchemaWrapper getDefaultSchema() { + DTPSchemaWrapper schema = this.getSchemaNamed(this.getConnectionProfile().getUserName()); + if (schema != null) { + return schema; + } + // PostgreSQL has a "schema search path" - the default is: + // "$user",public + // so if "$user" is not found, return public + if (this.getVendor().equals(POSTGRES_VENDOR)) { + return this.getSchemaNamed(POSTGRESQL_PUBLIC_SCHEMA_NAME); + } + // MySQL database has a single schema with the same name as the database + if (this.getVendor().equals(MYSQL_VENDOR)) { + return this.getSchemaNamed(this.getName()); + } + return null; } - // ********** Comparable implementation ********** + // ********** identifiers ********** - public int compareTo(Database database) { - return Collator.getInstance().compare(this.getName(), database.getName()); + /** + * Return the database object with the specified name. If the name is + * "delimited" (typically with double-quotes), it will be used without any + * folding. If the name is "normal" (i.e. not delimited), it will be + * folded to the appropriate case (typically uppercase). + * @see #identifierIsDelimited(String) + * @see #foldIdentifier(String) + * + * Since the database has the appropriate state to compare identifiers, + * the connection profile delegates to here when using the default + * "database finder". + */ + // TODO convert embedded quotes? + <T extends DatabaseObject> T getDatabaseObjectNamed_(T[] databaseObjects, String name) { + name = this.normalizeIdentifier(name); + for (T dbObject : databaseObjects) { + if (dbObject.getName().equals(name)) { + return dbObject; + } + } + return null; } + private String normalizeIdentifier(String identifier) { + if (this.identifierIsDelimited(identifier)) { + return StringTools.unwrap(identifier); + } + return this.foldIdentifier(identifier); + } - // ********** internal methods ********** + /** + * Return whether the specified identifier is "delimited" for the current + * database (typically with double-quotes). + */ + private boolean identifierIsDelimited(String identifier) { + if (this.vendorAllowsQuoteDelimiters() + && StringTools.stringIsQuoted(identifier)) { + return true; + } + if (this.vendorAllowsBracketDelimiters() + && StringTools.stringIsBracketed(identifier)) { + return true; + } + if (this.vendorAllowsBacktickDelimiters() + && StringTools.stringIsDelimited(identifier, BACKTICK)) { + return true; + } + return false; + } + + /** + * Return whether the database allows identifiers to delimited with + * quotes: "FOO". + */ + boolean vendorAllowsQuoteDelimiters() { + // all platforms allow identifiers to be delimited by quotes + return true; + } + + /** + * Return whether the database allows identifiers to delimited with + * brackets: [FOO]. + */ + boolean vendorAllowsBracketDelimiters() { + String vendor = this.getVendor(); + return vendor.equals(SQL_SERVER_VENDOR) + || vendor.equals(SYBASE_ASE_VENDOR) + || vendor.equals(SYBASE_ASA_VENDOR); + } + + /** + * Return whether the database allows identifiers to delimited with + * backticks: `FOO`. + */ + boolean vendorAllowsBacktickDelimiters() { + String vendor = this.getVendor(); + return vendor.equals(MYSQL_VENDOR); + } + + private static final char BACKTICK = '`'; + + /** + * Fold the specified identifier to the appropriate case. + * The SQL-92 spec says a "normal" (non-delimited) identifier should be + * folded to uppercase; but some databases do otherwise (e.g. PostgreSQL). + * + * According to on-line documentation I could find: ~bjv + * The following databases fold to uppercase: + * Derby + * Oracle + * DB2 + * HSQLDB + * MaxDB + * The following databases fold to lowercase: + * PostgreSQL + * Informix + * MySQL (sorta - depends on underlying O/S file system and env var) + * The following databases do not fold: + * MS SQL Server (might depend on collation setting...) + * Sybase (might depend on collation setting...) + */ + private String foldIdentifier(String identifier) { + if (this.vendorFoldsToLowercase()) { + return identifier.toLowerCase(); + } + if (this.vendorFoldsToUppercase()) { + return identifier.toUpperCase(); + } + if (this.vendorDoesNotFold()) { + return identifier; + } + throw new IllegalStateException("unknown vendor folding: " + this.getVendor()); //$NON-NLS-1$ + } + + /** + * Return whether the database folds non-delimited identifiers to lowercase. + */ + boolean vendorFoldsToLowercase() { + String vendor = this.getVendor(); + return vendor.equals(POSTGRES_VENDOR) + || vendor.equals(INFORMIX_VENDOR); + } + + /** + * Return whether the database does not fold non-delimited identifiers to + * lowercase. + */ + boolean vendorDoesNotFoldToLowercase() { + return ! this.vendorFoldsToLowercase(); + } + + /** + * Return whether the database folds non-delimited identifiers to uppercase. + */ + boolean vendorFoldsToUppercase() { + return this.vendorFolds() + && this.vendorDoesNotFoldToLowercase(); + } - boolean wraps(org.eclipse.datatools.modelbase.sql.schema.Database database) { - return this.dtpDatabase == database; + /** + * Return whether the database does not fold non-delimited identifiers to + * uppercase. + */ + boolean vendorDoesNotFoldToUppercase() { + return ! this.vendorFoldsToUppercase(); + } + + /** + * Return whether the database folds non-delimited identifiers to either + * uppercase or lowercase. + */ + boolean vendorFolds() { + return ! this.vendorDoesNotFold(); } /** - * return the table for the specified DTP table + * Return whether the database does not fold non-delimited identifiers to + * either uppercase or lowercase (i.e. the identifier is used unmodified). + * These guys are bit flaky, so we force an exact match. + * (e.g. MySQL folds database and table names to lowercase on Windows + * by default; but that default can be changed by the + * 'lower_case_table_names' system variable. This because databases are + * stored as directories and tables are stored as files in the underlying + * O/S, and the case-sensitivity of the names is determined by the behavior + * of filenames on the O/S. Then, to complicate things, + * none of the other identifiers, like table and column names, are folded; + * but they are case-insensitive, unless delimited. See + * http://dev.mysql.com/doc/refman/6.0/en/identifier-case-sensitivity.html.) */ - DTPTableWrapper table(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { - return this.schema(dtpTable.getSchema()).table(dtpTable); + boolean vendorDoesNotFold() { + String vendor = this.getVendor(); + return vendor.equals(SQL_SERVER_VENDOR) + || vendor.equals(SYBASE_ASE_VENDOR) + || vendor.equals(SYBASE_ASA_VENDOR) + || vendor.equals(MYSQL_VENDOR); } /** - * return the column for the specified DTP column + * Delimit the specified identifier in a vendor-appropriate fashion. */ - DTPColumnWrapper column(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { - return this.table(dtpColumn.getTable()).column(dtpColumn); + String delimitIdentifier(String identifier) { + if (this.vendorAllowsQuoteDelimiters()) { + return StringTools.quote(identifier); + } + throw new IllegalStateException("unknown vendor delimiters: " + this.getVendor()); //$NON-NLS-1$ + } + + + // ********** Comparable implementation ********** + + public int compareTo(Database database) { + return Collator.getInstance().compare(this.getName(), database.getName()); + } + + + // ********** internal methods ********** + + DatabaseDefinition getDTPDefinition() { + return RDBCorePlugin.getDefault().getDatabaseDefinitionRegistry().getDefinition(this.dtpDatabase); } + + // ********** listening ********** + @Override - DTPDatabaseWrapper database() { - return this; + synchronized void startListening() { + if (this.catalogs != null) { + this.startCatalogs(); + } + super.startListening(); } - - // ********** disposal ********** + private void startCatalogs() { + for (DTPCatalogWrapper catalog : this.catalogs) { + catalog.startListening(); + } + } - // must be public because it is defined in InternalDatabase interface @Override - public synchronized void dispose() { - super.dispose(); + synchronized void stopListening() { + if (this.catalogs != null) { + this.stopCatalogs(); + } + super.stopListening(); } + private void stopCatalogs() { + for (DTPCatalogWrapper catalog : this.catalogs) { + catalog.stopListening(); + } + } + + + // ********** clear ********** + @Override - void dispose_() { + void clear() { this.defaultCatalogCalculated = false; this.defaultCatalog = null; - this.disposeCatalogs(); - super.dispose_(); + if (this.catalogs != null) { + this.clearCatalogs(); + } + super.clear(); } - private void disposeCatalogs() { - if (this.catalogs != null) { - for (DTPCatalogWrapper catalog : this.catalogs) { - catalog.dispose(); - } - this.catalogs = null; + private void clearCatalogs() { + this.stopCatalogs(); + for (DTPCatalogWrapper catalog : this.catalogs) { + catalog.clear(); } + this.catalogs = null; } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPForeignKeyWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPForeignKeyWrapper.java index 74478aed5b..a605046f62 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPForeignKeyWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPForeignKeyWrapper.java @@ -26,12 +26,9 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; * Wrap a DTP ForeignKey */ final class DTPForeignKeyWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements ForeignKey { - // backpointer to parent - private final DTPTableWrapper baseTable; - // the wrapped DTP foreign key private final org.eclipse.datatools.modelbase.sql.constraints.ForeignKey dtpForeignKey; @@ -41,16 +38,15 @@ final class DTPForeignKeyWrapper // lazy-initialized private LocalColumnPair[] columnPairs; - // lazy-initialized - private String defaultEntityFieldName; - private boolean defaultEntityFieldNameCalculated = false; + // lazy-initialized - but it can be 'null' so we use a flag + private String defaultAttributeName; + private boolean defaultAttributeNameCalculated = false; // ********** constructor ********** DTPForeignKeyWrapper(DTPTableWrapper baseTable, org.eclipse.datatools.modelbase.sql.constraints.ForeignKey dtpForeignKey) { super(baseTable, dtpForeignKey); - this.baseTable = baseTable; this.dtpForeignKey = dtpForeignKey; } @@ -58,39 +54,52 @@ final class DTPForeignKeyWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - // clear stuff so it will be rebuilt - this.dispose_(); - this.getConnectionProfile().foreignKeyChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().foreignKeyChanged(this); + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.getName() + ": " + Arrays.asList(this.getColumnPairs())); //$NON-NLS-1$ } // ********** ForeignKey implementation ********** - @Override public String getName() { return this.dtpForeignKey.getName(); } public DTPTableWrapper getBaseTable() { - return this.baseTable; + return (DTPTableWrapper) this.getParent(); } public synchronized DTPTableWrapper getReferencedTable() { if (this.referencedTable == null) { - this.referencedTable = this.baseTable.table(this.dtpForeignKey.getUniqueConstraint().getBaseTable()); + this.referencedTable = this.getBaseTable().getTable(this.dtpForeignKey.getUniqueConstraint().getBaseTable()); } return this.referencedTable; } + public boolean referencesSingleColumnPrimaryKey() { + if (this.columnPairsSize() != 1) { + return false; + } + if (this.getReferencedTable().primaryKeyColumnsSize() != 1) { + return false; + } + return this.getColumnPair().getReferencedColumn() == this.getReferencedTable().getPrimaryKeyColumn(); + } + // ***** column pairs public Iterator<ColumnPair> columnPairs() { - return new ArrayIterator<ColumnPair>(this.columnPairs_()); + return new ArrayIterator<ColumnPair>(this.getColumnPairs()); } - public LocalColumnPair columnPair() { - LocalColumnPair[] pairs = this.columnPairs_(); + public LocalColumnPair getColumnPair() { + LocalColumnPair[] pairs = this.getColumnPairs(); if (pairs.length != 1) { throw new IllegalStateException("multiple column pairs: " + pairs.length); //$NON-NLS-1$ } @@ -98,10 +107,10 @@ final class DTPForeignKeyWrapper } private Iterator<LocalColumnPair> localColumnPairs() { - return new ArrayIterator<LocalColumnPair>(this.columnPairs_()); + return new ArrayIterator<LocalColumnPair>(this.getColumnPairs()); } - private synchronized LocalColumnPair[] columnPairs_() { + private synchronized LocalColumnPair[] getColumnPairs() { if (this.columnPairs == null) { this.columnPairs = this.buildColumnPairs(); } @@ -109,43 +118,44 @@ final class DTPForeignKeyWrapper } private LocalColumnPair[] buildColumnPairs() { - List<org.eclipse.datatools.modelbase.sql.tables.Column> baseColumns = this.dtpBaseColumns(); + List<org.eclipse.datatools.modelbase.sql.tables.Column> baseColumns = this.getDTPBaseColumns(); int size = baseColumns.size(); - List<org.eclipse.datatools.modelbase.sql.tables.Column> refColumns = this.dtpRefColumns(); + List<org.eclipse.datatools.modelbase.sql.tables.Column> refColumns = this.getDTPReferenceColumns(); if (refColumns.size() != size) { - throw new IllegalStateException(this.getBaseTable().getName() + "." + this.getName() + //$NON-NLS-1$ + throw new IllegalStateException(this.getBaseTable().getName() + '.' + this.getName() + " - mismatched sizes: " + size + " vs. " + refColumns.size()); //$NON-NLS-1$ //$NON-NLS-2$ } LocalColumnPair[] result = new LocalColumnPair[baseColumns.size()]; for (int i = baseColumns.size(); i-- > 0; ) { - DTPColumnWrapper baseColumn = this.baseTable.column(baseColumns.get(i)); - DTPColumnWrapper refColumn = this.baseTable.column(refColumns.get(i)); - result[i] = new LocalColumnPair(baseColumn, refColumn); + result[i] = new LocalColumnPair( + this.getBaseTable().getColumn(baseColumns.get(i)), + this.getBaseTable().getColumn(refColumns.get(i)) + ); } return result; } // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpBaseColumns() { + private List<org.eclipse.datatools.modelbase.sql.tables.Column> getDTPBaseColumns() { return this.dtpForeignKey.getMembers(); } // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpRefColumns() { + private List<org.eclipse.datatools.modelbase.sql.tables.Column> getDTPReferenceColumns() { return this.dtpForeignKey.getUniqueConstraint().getMembers(); } public int columnPairsSize() { - return this.columnPairs_().length; + return this.getColumnPairs().length; } public Iterator<Column> baseColumns() { return new TransformationIterator<LocalColumnPair, Column>(this.localColumnPairs()) { @Override protected Column transform(LocalColumnPair pair) { - return pair.baseColumn(); + return pair.getBaseColumn(); } }; } @@ -158,7 +168,7 @@ final class DTPForeignKeyWrapper return new FilteringIterator<Column, Column>(this.baseColumns()) { @Override protected boolean accept(Column column) { - return ! DTPForeignKeyWrapper.this.getBaseTable().primaryKeyColumnsContains(column); + return ! column.isPrimaryKeyColumn(); } }; } @@ -167,41 +177,33 @@ final class DTPForeignKeyWrapper return new TransformationIterator<LocalColumnPair, Column>(this.localColumnPairs()) { @Override protected Column transform(LocalColumnPair columnPair) { - return columnPair.referencedColumn(); + return columnPair.getReferencedColumn(); } }; } - // ***** default entity field name + // ***** attribute name - /** - * If the name of the "base" column adheres to the EJB standard for a - * default mapping (i.e. it ends with an underscore followed by the name - * of the "referenced" column, and the "referenced" column is the single - * primary key column of the "referenced" table), return the corresponding - * default entity field name: - * ForeignKey(EMP.CUBICLE_ID => CUBICLE.ID) => "CUBICLE" - * Return a null if it does not adhere to the EJB standard: - * ForeignKey(EMP.CUBICLE_ID => CUBICLE.CUBICLE_ID) => null - */ - private synchronized String defaultEntityFieldName() { - if ( ! this.defaultEntityFieldNameCalculated) { - this.defaultEntityFieldNameCalculated = true; - this.defaultEntityFieldName = this.buildDefaultEntityFieldName(); + public String getAttributeName() { + String defaultName = this.getDefaultAttributeName(); + return (defaultName != null) ? defaultName : this.getNonDefaultAttributeName(); + } + + public synchronized String getDefaultAttributeName() { + if ( ! this.defaultAttributeNameCalculated) { + this.defaultAttributeNameCalculated = true; + this.defaultAttributeName = this.buildDefaultAttributeName(); } - return this.defaultEntityFieldName; + return this.defaultAttributeName; } - /** - * @see #defaultEntityFieldName() - */ - private String buildDefaultEntityFieldName() { + private String buildDefaultAttributeName() { if ( ! this.referencesSingleColumnPrimaryKey()) { return null; } - LocalColumnPair columnPair = this.columnPairs_()[0]; - String baseColName = columnPair.baseColumn().getName(); - String refColName = columnPair.referencedColumn().getName(); + LocalColumnPair columnPair = this.getColumnPair(); + String baseColName = columnPair.getBaseColumn().getName(); + String refColName = columnPair.getReferencedColumn().getName(); if (baseColName.length() <= (refColName.length() + 1)) { return null; } @@ -212,65 +214,68 @@ final class DTPForeignKeyWrapper if (baseColName.charAt(_index) != '_') { return null; } - String name = baseColName.substring(0, _index); - return this.isCaseSensitive() ? name : name.toLowerCase(); - } - - // ***** miscellaneous - - public String getJavaFieldName() { - String fieldName = this.defaultEntityFieldName(); - return (fieldName != null) ? fieldName : this.nonDefaultEntityFieldName(); + return baseColName.substring(0, _index); } - public boolean defaultMatchesJavaFieldName(String javaFieldName) { - return this.isCaseSensitive() ? - javaFieldName.equals(this.defaultEntityFieldName()) - : - javaFieldName.equalsIgnoreCase(this.defaultEntityFieldName()); - } - - public boolean isDefaultFor(String javaFieldName) { - if (this.columnPairsSize() != 1) { - return false; - } - - if (this.getReferencedTable().primaryKeyColumnsSize() != 1) { - return false; - } - - LocalColumnPair columnPair = this.columnPairs_()[0]; - Column pkColumn = this.getReferencedTable().primaryKeyColumn(); - if (columnPair.referencedColumn() != pkColumn) { - return false; - } - - return columnPair.baseColumn().matchesJavaFieldName(javaFieldName + "_" + pkColumn.getName()); //$NON-NLS-1$ + /** + * If this is a simple (single-column) foreign key, use the name of the + * single base column to build a name. If this is a compound foreign key, + * return the name of the referenced table. + */ + // TODO if there is only one FK to a given table, use the table's name instead of the column's name? + private String getNonDefaultAttributeName() { + return (this.columnPairsSize() == 1) ? + this.getNonDefaultAttributeNameFromBaseColumn() + : + this.getReferencedTable().getName(); } - public boolean referencesSingleColumnPrimaryKey() { - if (this.columnPairsSize() != 1) { - return false; - } - if (this.getReferencedTable().primaryKeyColumnsSize() != 1) { - return false; + /** + * The underscore check is helpful when the referenced column is NOT the + * primary key of the referenced table (i.e. it has only a UNIQUE constraint). + * ForeignKey(EMP.CUBICLE_ID => CUBICLE.ID) => "CUBICLE" + * ForeignKey(EMP.CUBICLEID => CUBICLE.ID) => "CUBICLE" + * ForeignKey(EMP.CUBICLE_PK => CUBICLE.ID) => "CUBICLE_PK" + */ + private String getNonDefaultAttributeNameFromBaseColumn() { + LocalColumnPair columnPair = this.getColumnPair(); + String baseColName = columnPair.getBaseColumn().getName(); + String refColName = columnPair.getReferencedColumn().getName(); + int len = baseColName.length(); + int refLen = refColName.length(); + if ((len > refLen) && baseColName.endsWith(refColName)) { + len = len - refLen; + if ((len > 1) && baseColName.charAt(len - 1) == '_') { + len = len - 1; + } } - - return this.columnPair().referencedColumn() == this.getReferencedTable().primaryKeyColumn(); + return baseColName.substring(0, len); } /** - * If this is a simple (single-column) foreign key, return the java field - * name of the single base column. If this is a compound foreign key, - * return the java field name of the referenced table. + * Examples: + * Oracle etc. + * ForeignKey(FOO_ID => ID) vs. "foo" => null + * ForeignKey(FOO_ID => FOO_ID) vs. "foo" => "FOO_ID" + * ForeignKey(FOO => ID) vs. "foo" => "FOO" + * ForeignKey(Foo_ID => ID) vs. "foo" => "\"Foo_ID\"" + * + * PostgreSQL etc. + * ForeignKey(foo_id => id) vs. "foo" => null + * ForeignKey(foo_id => foo_id) vs. "foo" => "foo_id" + * ForeignKey(foo => id) vs. "foo" => "foo" + * ForeignKey(Foo_ID => ID) vs. "foo" => "\"Foo_ID\"" + * + * SQL Server etc. + * ForeignKey(foo_ID => ID) vs. "foo" => null + * ForeignKey(FOO_ID => FOO_ID) vs. "foo" => "FOO_ID" + * ForeignKey(FOO => ID) vs. "foo" => "FOO" + * ForeignKey(Foo_ID => ID) vs. "foo" => "Foo_ID" */ - // TODO if there is only one FK to a given table, use the table's name instead of the column's name? - // TODO if the FK column name ends with the PK column name, strip the PK column name? - private String nonDefaultEntityFieldName() { - return (this.columnPairsSize() == 1) ? - this.columnPair().baseColumn().getJavaFieldName() - : - this.getReferencedTable().getJavaFieldName(); + public String getJoinColumnAnnotationIdentifier(String attributeName) { + String defaultBaseColumnName = attributeName + '_' + this.getReferencedTable().getPrimaryKeyColumn().getName(); + String baseColumnName = this.getColumnPair().getBaseColumn().getName(); + return this.getAnnotationIdentifier(defaultBaseColumnName, baseColumnName); } @@ -287,33 +292,12 @@ final class DTPForeignKeyWrapper return this.dtpForeignKey == foreignKey; } - boolean isCaseSensitive() { - return this.baseTable.isCaseSensitive(); - } - - DTPDatabaseWrapper database() { - return this.baseTable.database(); - } - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.getName() + ": " + Arrays.asList(this.columnPairs_())); //$NON-NLS-1$ - } - - - // ********** disposal ********** - @Override - synchronized void dispose() { - this.dispose_(); - super.dispose(); - } - - private void dispose_() { + void clear() { // the foreign key does not "contain" any other objects, - // so we don't need to forward the #dispose() - this.defaultEntityFieldNameCalculated = false; - this.defaultEntityFieldName = null; + // so we don't need to forward the #clear() + this.defaultAttributeNameCalculated = false; + this.defaultAttributeName = null; this.columnPairs = null; this.referencedTable = null; } @@ -327,31 +311,25 @@ final class DTPForeignKeyWrapper LocalColumnPair(DTPColumnWrapper baseColumn, DTPColumnWrapper referencedColumn) { super(); + if ((baseColumn == null) || (referencedColumn == null)) { + throw new NullPointerException(); + } this.baseColumn = baseColumn; this.referencedColumn = referencedColumn; } - - // ********** ColumnPair implementation ********** - - public DTPColumnWrapper baseColumn() { + public DTPColumnWrapper getBaseColumn() { return this.baseColumn; } - public DTPColumnWrapper referencedColumn() { + public DTPColumnWrapper getReferencedColumn() { return this.referencedColumn; } - - // ********** Comparable implementation ********** - public int compareTo(ColumnPair columnPair) { - return Collator.getInstance().compare(this.baseColumn().getName(), columnPair.baseColumn().getName()); + return Collator.getInstance().compare(this.getBaseColumn().getName(), columnPair.getBaseColumn().getName()); } - - // ********** Object overrides ********** - @Override public String toString() { return StringTools.buildToStringFor(this, this.baseColumn.getName() + "=>" + this.referencedColumn.getName()); //$NON-NLS-1$ diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaContainerWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaContainerWrapper.java index 21a13551ad..0323456f89 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaContainerWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaContainerWrapper.java @@ -14,7 +14,6 @@ import java.util.List; import org.eclipse.jpt.db.Schema; import org.eclipse.jpt.db.SchemaContainer; -import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; @@ -22,7 +21,7 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; * Coalesce behavior for a schema container (i.e. database or catalog). */ abstract class DTPSchemaContainerWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements SchemaContainer { // lazy-initialized @@ -31,40 +30,86 @@ abstract class DTPSchemaContainerWrapper // ********** constructor ********** - DTPSchemaContainerWrapper(ConnectionProfileHolder connectionProfileHolder, Object dtpObject) { - super(connectionProfileHolder, dtpObject); + DTPSchemaContainerWrapper(DTPDatabaseObject parent, Object dtpObject) { + super(parent, dtpObject); } // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - // clear stuff so it will be rebuilt - this.dispose_(); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); } // ********** abstract methods ********** - abstract DTPDatabaseWrapper database(); + /** + * return the schema container's DTP schemata + */ + abstract List<org.eclipse.datatools.modelbase.sql.schema.Schema> getDTPSchemata(); + + /** + * return the schema container's catalog, + * null if the database does not support catalogs + */ + abstract DTPCatalogWrapper getCatalog(); + + /** + * return the schema for the specified DTP schema + */ + abstract DTPSchemaWrapper getSchema(org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema); + + /** + * assume the schema container (database or catalog) contains + * the specified schema + */ + DTPSchemaWrapper getSchema_(org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema) { + for (DTPSchemaWrapper schema : this.getSchemata()) { + if (schema.wraps(dtpSchema)) { + return schema; + } + } + throw new IllegalArgumentException("invalid DTP schema: " + dtpSchema); //$NON-NLS-1$ + } - abstract boolean isCaseSensitive(); + /** + * return the table for the specified DTP table + */ + abstract DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable); - abstract List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata(); + /** + * assume the schema container contains the specified table + */ + DTPTableWrapper getTable_(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { + return this.getSchema_(dtpTable.getSchema()).getTable_(dtpTable); + } + + /** + * return the column for the specified DTP column + */ + abstract DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn); + + /** + * assume the schema container contains the specified column + */ + DTPColumnWrapper getColumn_(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + return this.getTable_(dtpColumn.getTable()).getColumn_(dtpColumn); + } // ********** schemata ********** public Iterator<Schema> schemata() { - return new ArrayIterator<Schema>(this.schemata_()); + return new ArrayIterator<Schema>(this.getSchemata()); } - private Iterator<DTPSchemaWrapper> schemaWrappers() { - return new ArrayIterator<DTPSchemaWrapper>(this.schemata_()); + Iterator<DTPSchemaWrapper> schemaWrappers() { + return new ArrayIterator<DTPSchemaWrapper>(this.getSchemata()); } - synchronized DTPSchemaWrapper[] schemata_() { + synchronized DTPSchemaWrapper[] getSchemata() { if (this.schemata == null) { this.schemata = this.buildSchemata(); } @@ -72,7 +117,7 @@ abstract class DTPSchemaContainerWrapper } private DTPSchemaWrapper[] buildSchemata() { - List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata = this.dtpSchemata(); + List<org.eclipse.datatools.modelbase.sql.schema.Schema> dtpSchemata = this.getDTPSchemata(); DTPSchemaWrapper[] result = new DTPSchemaWrapper[dtpSchemata.size()]; for (int i = result.length; i-- > 0;) { result[i] = new DTPSchemaWrapper(this, dtpSchemata.get(i)); @@ -81,7 +126,7 @@ abstract class DTPSchemaContainerWrapper } public int schemataSize() { - return this.schemata_().length; + return this.getSchemata().length; } public Iterator<String> schemaNames() { @@ -93,67 +138,57 @@ abstract class DTPSchemaContainerWrapper }; } - public boolean containsSchemaNamed(String name) { - return this.schemaNamed(name) != null; + public DTPSchemaWrapper getSchemaNamed(String name) { + return this.getDatabaseObjectNamed(this.getSchemata(), name); } - public DTPSchemaWrapper schemaNamed(String name) { - return this.isCaseSensitive() ? this.schemaNamedCaseSensitive(name) : this.schemaNamedIgnoreCase(name); + + // ********** listening ********** + + @Override + synchronized void startListening() { + if (this.schemata != null) { + this.startSchemata(); + } + super.startListening(); } - private DTPSchemaWrapper schemaNamedCaseSensitive(String name) { - for (Iterator<DTPSchemaWrapper> stream = this.schemaWrappers(); stream.hasNext(); ) { - DTPSchemaWrapper schema = stream.next(); - if (schema.getName().equals(name)) { - return schema; - } + private void startSchemata() { + for (DTPSchemaWrapper schema : this.schemata) { + schema.startListening(); } - return null; } - - private DTPSchemaWrapper schemaNamedIgnoreCase(String name) { - for (Iterator<DTPSchemaWrapper> stream = this.schemaWrappers(); stream.hasNext(); ) { - DTPSchemaWrapper schema = stream.next(); - if (StringTools.stringsAreEqualIgnoreCase(schema.getName(), name)) { - return schema; - } + + @Override + synchronized void stopListening() { + if (this.schemata != null) { + this.stopSchemata(); } - return null; + super.stopListening(); } - /** - * return the schema for the specified DTP schema - */ - DTPSchemaWrapper schema(org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema) { - for (Iterator<DTPSchemaWrapper> stream = this.schemaWrappers(); stream.hasNext(); ) { - DTPSchemaWrapper schema = stream.next(); - if (schema.wraps(dtpSchema)) { - return schema; - } + private void stopSchemata() { + for (DTPSchemaWrapper schema : this.schemata) { + schema.stopListening(); } - throw new IllegalArgumentException("invalid DTP schema: " + dtpSchema); //$NON-NLS-1$ } - // ********** disposal ********** + // ********** clear ********** @Override - synchronized void dispose() { - this.dispose_(); - super.dispose(); - } - - void dispose_() { - this.disposeSchemata(); + synchronized void clear() { + if (this.schemata != null) { + this.clearSchemata(); + } } - private void disposeSchemata() { - if (this.schemata != null) { - for (DTPSchemaWrapper schema : this.schemata) { - schema.dispose(); - } - this.schemata = null; + private void clearSchemata() { + this.stopSchemata(); + for (DTPSchemaWrapper schema : this.schemata) { + schema.clear(); } + this.schemata = null; } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaWrapper.java index 270f3d711c..3d3a2938d3 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSchemaWrapper.java @@ -13,10 +13,10 @@ import java.text.Collator; import java.util.Iterator; import java.util.List; +import org.eclipse.jpt.db.Catalog; import org.eclipse.jpt.db.Schema; import org.eclipse.jpt.db.Sequence; import org.eclipse.jpt.db.Table; -import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; @@ -24,12 +24,9 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; * Wrap a DTP Schema */ final class DTPSchemaWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements Schema { - // backpointer to parent - private final DTPSchemaContainerWrapper container; - // the wrapped DTP schema private final org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema; @@ -44,7 +41,6 @@ final class DTPSchemaWrapper DTPSchemaWrapper(DTPSchemaContainerWrapper container, org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema) { super(container, dtpSchema); - this.container = container; this.dtpSchema = dtpSchema; } @@ -52,31 +48,33 @@ final class DTPSchemaWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - // clear stuff so it can be rebuilt - this.dispose_(); - this.getConnectionProfile().schemaChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().schemaChanged(this); } // ********** Schema implementation ********** - @Override public String getName() { return this.dtpSchema.getName(); } + public Catalog getCatalog() { + return this.getContainer().getCatalog(); + } + // ***** tables public Iterator<Table> tables() { - return new ArrayIterator<Table>(this.tables_()); + return new ArrayIterator<Table>(this.getTables()); } private Iterator<DTPTableWrapper> tableWrappers() { - return new ArrayIterator<DTPTableWrapper>(this.tables_()); + return new ArrayIterator<DTPTableWrapper>(this.getTables()); } - private synchronized DTPTableWrapper[] tables_() { + private synchronized DTPTableWrapper[] getTables() { if (this.tables == null) { this.tables = this.buildTables(); } @@ -84,7 +82,7 @@ final class DTPSchemaWrapper } private DTPTableWrapper[] buildTables() { - List<org.eclipse.datatools.modelbase.sql.tables.Table> dtpTables = this.dtpTables(); + List<org.eclipse.datatools.modelbase.sql.tables.Table> dtpTables = this.getDTPTables(); DTPTableWrapper[] result = new DTPTableWrapper[dtpTables.size()]; for (int i = result.length; i-- > 0;) { result[i] = new DTPTableWrapper(this, dtpTables.get(i)); @@ -94,12 +92,12 @@ final class DTPSchemaWrapper // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.tables.Table> dtpTables() { + private List<org.eclipse.datatools.modelbase.sql.tables.Table> getDTPTables() { return this.dtpSchema.getTables(); } public int tablesSize() { - return this.tables_().length; + return this.getTables().length; } public Iterator<String> tableNames() { @@ -111,43 +109,22 @@ final class DTPSchemaWrapper }; } - public boolean containsTableNamed(String name) { - return this.tableNamed(name) != null; - } - - public DTPTableWrapper tableNamed(String name) { - return this.isCaseSensitive() ? this.tableNamedCaseSensitive(name) : this.tableNamedIgnoreCase(name); - } - - private DTPTableWrapper tableNamedCaseSensitive(String name) { - for (Iterator<DTPTableWrapper> stream = this.tableWrappers(); stream.hasNext(); ) { - DTPTableWrapper table = stream.next(); - if (table.getName().equals(name)) { - return table; - } - } - return null; - } - - private DTPTableWrapper tableNamedIgnoreCase(String name) { - for (Iterator<DTPTableWrapper> stream = this.tableWrappers(); stream.hasNext(); ) { - DTPTableWrapper table = stream.next(); - if (StringTools.stringsAreEqualIgnoreCase(table.getName(), name)) { - return table; - } - } - return null; + /** + * return the table for the specified DTP table + */ + DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { + // try to short-circuit the search + return this.wraps(dtpTable.getSchema()) ? + this.getTable_(dtpTable) + : + this.getContainer().getTable(dtpTable); } /** - * return the table for the specified DTP table + * assume the schema contains the specified table */ - DTPTableWrapper table(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { - if (dtpTable.getSchema() != this.dtpSchema) { - return this.database().table(dtpTable); - } - for (Iterator<DTPTableWrapper> stream = this.tableWrappers(); stream.hasNext(); ) { - DTPTableWrapper table = stream.next(); + DTPTableWrapper getTable_(org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { + for (DTPTableWrapper table : this.getTables()) { if (table.wraps(dtpTable)) { return table; } @@ -155,17 +132,21 @@ final class DTPSchemaWrapper throw new IllegalArgumentException("invalid DTP table: " + dtpTable); //$NON-NLS-1$ } + public DTPTableWrapper getTableNamed(String name) { + return this.getDatabaseObjectNamed(this.getTables(), name); + } + // ***** sequences public Iterator<Sequence> sequences() { - return new ArrayIterator<Sequence>(this.sequences_()); + return new ArrayIterator<Sequence>(this.getSequences()); } private Iterator<DTPSequenceWrapper> sequenceWrappers() { - return new ArrayIterator<DTPSequenceWrapper>(this.sequences_()); + return new ArrayIterator<DTPSequenceWrapper>(this.getSequences()); } - private synchronized DTPSequenceWrapper[] sequences_() { + private synchronized DTPSequenceWrapper[] getSequences() { if (this.sequences == null) { this.sequences = this.buildSequences(); } @@ -173,7 +154,7 @@ final class DTPSchemaWrapper } private DTPSequenceWrapper[] buildSequences() { - List<org.eclipse.datatools.modelbase.sql.schema.Sequence> dtpSequences = this.dtpSequences(); + List<org.eclipse.datatools.modelbase.sql.schema.Sequence> dtpSequences = this.getDTPSequences(); DTPSequenceWrapper[] result = new DTPSequenceWrapper[dtpSequences.size()]; for (int i = result.length; i-- > 0;) { result[i] = new DTPSequenceWrapper(this, dtpSequences.get(i)); @@ -183,12 +164,12 @@ final class DTPSchemaWrapper // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.schema.Sequence> dtpSequences() { + private List<org.eclipse.datatools.modelbase.sql.schema.Sequence> getDTPSequences() { return this.dtpSchema.getSequences(); } public int sequencesSize() { - return this.sequences_().length; + return this.getSequences().length; } public Iterator<String> sequenceNames() { @@ -200,32 +181,8 @@ final class DTPSchemaWrapper }; } - public boolean containsSequenceNamed(String name) { - return this.sequenceNamed(name) != null; - } - - public DTPSequenceWrapper sequenceNamed(String name) { - return this.isCaseSensitive() ? this.sequenceNamedCaseSensitive(name) : this.sequenceNamedIgnoreCase(name); - } - - private DTPSequenceWrapper sequenceNamedCaseSensitive(String name) { - for (Iterator<DTPSequenceWrapper> stream = this.sequenceWrappers(); stream.hasNext(); ) { - DTPSequenceWrapper sequence = stream.next(); - if (sequence.getName().equals(name)) { - return sequence; - } - } - return null; - } - - private DTPSequenceWrapper sequenceNamedIgnoreCase(String name) { - for (Iterator<DTPSequenceWrapper> stream = this.sequenceWrappers(); stream.hasNext(); ) { - DTPSequenceWrapper sequence = stream.next(); - if (sequence.getName().equalsIgnoreCase(name)) { - return sequence; - } - } - return null; + public DTPSequenceWrapper getSequenceNamed(String name) { + return this.getDatabaseObjectNamed(this.getSequences(), name); } @@ -242,48 +199,103 @@ final class DTPSchemaWrapper return this.dtpSchema == schema; } - boolean isCaseSensitive() { - return this.database().isCaseSensitive(); + /** + * return the column for the specified DTP column + */ + DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + return this.wraps(dtpColumn.getTable().getSchema()) ? + this.getColumn_(dtpColumn) + : + this.getContainer().getColumn(dtpColumn); } - DTPColumnWrapper column(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { - return this.database().column(dtpColumn); + /** + * assume the schema contains the specified column + */ + DTPColumnWrapper getColumn_(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + return this.getTable_(dtpColumn.getTable()).getColumn_(dtpColumn); } - DTPDatabaseWrapper database() { - return this.container.database(); + private DTPSchemaContainerWrapper getContainer() { + return (DTPSchemaContainerWrapper) this.getParent(); } - // ********** disposal ********** + // ********** listening ********** @Override - synchronized void dispose() { - this.dispose_(); - super.dispose(); + synchronized void startListening() { + if (this.sequences != null) { + this.startSequences(); + } + if (this.tables != null) { + this.startTables(); + } + super.startListening(); } - private void dispose_() { - this.disposeSequences(); - this.disposeTables(); + private void startSequences() { + for (DTPSequenceWrapper sequence : this.sequences) { + sequence.startListening(); + } } - private void disposeSequences() { + private void startTables() { + for (DTPTableWrapper table : this.tables) { + table.startListening(); + } + } + + @Override + synchronized void stopListening() { if (this.sequences != null) { - for (DTPSequenceWrapper sequence : this.sequences) { - sequence.dispose(); - } - this.sequences = null; + this.stopSequences(); } + if (this.tables != null) { + this.stopTables(); + } + super.stopListening(); } - private void disposeTables() { + private void stopSequences() { + for (DTPSequenceWrapper sequence : this.sequences) { + sequence.stopListening(); + } + } + + private void stopTables() { + for (DTPTableWrapper table : this.tables) { + table.stopListening(); + } + } + + + // ********** clear ********** + + @Override + synchronized void clear() { + if (this.sequences != null) { + this.clearSequences(); + } if (this.tables != null) { - for (DTPTableWrapper table : this.tables) { - table.dispose(); - } - this.tables = null; + this.clearTables(); + } + } + + private void clearSequences() { + this.stopSequences(); + for (DTPSequenceWrapper sequence : this.sequences) { + sequence.clear(); + } + this.sequences = null; + } + + private void clearTables() { + this.stopTables(); + for (DTPTableWrapper table : this.tables) { + table.clear(); } + this.tables = null; } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSequenceWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSequenceWrapper.java index b1e546bd07..aa501051aa 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSequenceWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPSequenceWrapper.java @@ -17,12 +17,9 @@ import org.eclipse.jpt.db.Sequence; * Wrap a DTP Sequence */ final class DTPSequenceWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements Sequence { - // backpointer to parent - private final DTPSchemaWrapper schema; - // the wrapped DTP sequence private final org.eclipse.datatools.modelbase.sql.schema.Sequence dtpSequence; @@ -31,7 +28,6 @@ final class DTPSequenceWrapper DTPSequenceWrapper(DTPSchemaWrapper schema, org.eclipse.datatools.modelbase.sql.schema.Sequence dtpSequence) { super(schema, dtpSequence); - this.schema = schema; this.dtpSequence = dtpSequence; } @@ -39,18 +35,22 @@ final class DTPSequenceWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - this.getConnectionProfile().sequenceChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().sequenceChanged(this); } // ********** Sequence implementation ********** - @Override public String getName() { return this.dtpSequence.getName(); } + public DTPSchemaWrapper getSchema() { + return (DTPSchemaWrapper) this.getParent(); + } + // ********** Comparable implementation ********** @@ -65,12 +65,9 @@ final class DTPSequenceWrapper return this.dtpSequence == sequence; } - boolean isCaseSensitive() { - return this.schema.isCaseSensitive(); - } - - DTPDatabaseWrapper database() { - return this.schema.database(); + @Override + void clear() { + // no state to clear } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPTableWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPTableWrapper.java index f5db4d69cd..fc50bc4913 100644 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPTableWrapper.java +++ b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPTableWrapper.java @@ -19,8 +19,6 @@ import org.eclipse.jpt.db.Column; import org.eclipse.jpt.db.ForeignKey; import org.eclipse.jpt.db.Table; import org.eclipse.jpt.utility.internal.CollectionTools; -import org.eclipse.jpt.utility.internal.NameTools; -import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; @@ -28,12 +26,9 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; * Wrap a DTP Table */ final class DTPTableWrapper - extends DTPWrapper + extends DTPDatabaseObjectWrapper implements Table { - // backpointer to parent - private final DTPSchemaWrapper schema; - // the wrapped DTP table private final org.eclipse.datatools.modelbase.sql.tables.Table dtpTable; @@ -55,7 +50,6 @@ final class DTPTableWrapper DTPTableWrapper(DTPSchemaWrapper schema, org.eclipse.datatools.modelbase.sql.tables.Table dtpTable) { super(schema, dtpTable); - this.schema = schema; this.dtpTable = dtpTable; } @@ -63,54 +57,33 @@ final class DTPTableWrapper // ********** DTPWrapper implementation ********** @Override - synchronized void catalogObjectChanged(int eventType) { - // clear stuff so it can be rebuilt - this.dispose_(); - this.getConnectionProfile().tableChanged(this, eventType); + synchronized void catalogObjectChanged() { + super.catalogObjectChanged(); + this.getConnectionProfile().tableChanged(this); } // ********** Table implementation ********** - @Override public String getName() { return this.dtpTable.getName(); } - public String getShortJavaClassName() { - String jName = this.getName(); - if ( ! this.isCaseSensitive()) { - jName = StringTools.capitalize(jName.toLowerCase()); - } - return NameTools.convertToJavaIdentifier(jName); - } - - public boolean matchesShortJavaClassName(String shortJavaClassName) { - return this.isCaseSensitive() ? - this.getName().equals(shortJavaClassName) - : - this.getName().equalsIgnoreCase(shortJavaClassName); - } - - public String getJavaFieldName() { - String jName = this.getName(); - if ( ! this.isCaseSensitive()) { - jName = jName.toLowerCase(); - } - return NameTools.convertToJavaIdentifier(jName); + public DTPSchemaWrapper getSchema() { + return (DTPSchemaWrapper) this.getParent(); } // ***** columns public Iterator<Column> columns() { - return new ArrayIterator<Column>(this.columns_()); + return new ArrayIterator<Column>(this.getColumns()); } private Iterator<DTPColumnWrapper> columnWrappers() { - return new ArrayIterator<DTPColumnWrapper>(this.columns_()); + return new ArrayIterator<DTPColumnWrapper>(this.getColumns()); } - private synchronized DTPColumnWrapper[] columns_() { + private synchronized DTPColumnWrapper[] getColumns() { if (this.columns == null) { this.columns = this.buildColumns(); } @@ -118,7 +91,7 @@ final class DTPTableWrapper } private DTPColumnWrapper[] buildColumns() { - List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns = this.dtpColumns(); + List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns = this.getDTPColumns(); DTPColumnWrapper[] result = new DTPColumnWrapper[dtpColumns.size()]; for (int i = result.length; i-- > 0;) { result[i] = new DTPColumnWrapper(this, dtpColumns.get(i)); @@ -128,12 +101,12 @@ final class DTPTableWrapper // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.tables.Column> dtpColumns() { + private List<org.eclipse.datatools.modelbase.sql.tables.Column> getDTPColumns() { return this.dtpTable.getColumns(); } public int columnsSize() { - return this.columns_().length; + return this.getColumns().length; } public Iterator<String> columnNames() { @@ -145,42 +118,22 @@ final class DTPTableWrapper }; } - public boolean containsColumnNamed(String name) { - return this.columnNamed(name) != null; - } - - public DTPColumnWrapper columnNamed(String name) { - return this.isCaseSensitive() ? this.columnNamedCaseSensitive(name) : this.columnNamedIgnoreCase(name); - } - - private DTPColumnWrapper columnNamedCaseSensitive(String name) { - for (Iterator<DTPColumnWrapper> stream = this.columnWrappers(); stream.hasNext(); ) { - DTPColumnWrapper column = stream.next(); - if (column.getName().equals(name)) { - return column; - } - } - return null; - } - - private DTPColumnWrapper columnNamedIgnoreCase(String name) { - for (Iterator<DTPColumnWrapper> stream = this.columnWrappers(); stream.hasNext(); ) { - DTPColumnWrapper column = stream.next(); - if (StringTools.stringsAreEqualIgnoreCase(column.getName(), name)) { - return column; - } - } - return null; + /** + * return the column for the specified DTP column + */ + DTPColumnWrapper getColumn(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + // try to short-circuit the search + return this.wraps(dtpColumn.getTable()) ? + this.getColumn_(dtpColumn) + : + this.getSchema().getColumn(dtpColumn); } /** - * return the column for the specified DTP column + * assume the table contains the specified column */ - DTPColumnWrapper column(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { - if (dtpColumn.getTable() != this.dtpTable) { - return this.schema.column(dtpColumn); - } - for (DTPColumnWrapper column : this.columns_()) { + DTPColumnWrapper getColumn_(org.eclipse.datatools.modelbase.sql.tables.Column dtpColumn) { + for (DTPColumnWrapper column : this.getColumns()) { if (column.wraps(dtpColumn)) { return column; } @@ -188,21 +141,25 @@ final class DTPTableWrapper throw new IllegalArgumentException("invalid DTP column: " + dtpColumn); //$NON-NLS-1$ } + public DTPColumnWrapper getColumnNamed(String name) { + return this.getDatabaseObjectNamed(this.getColumns(), name); + } + // ***** primaryKeyColumns public Iterator<Column> primaryKeyColumns() { - return new ArrayIterator<Column>(this.primaryKeyColumns_()); + return new ArrayIterator<Column>(this.getPrimaryKeyColumns()); } - public DTPColumnWrapper primaryKeyColumn() { - DTPColumnWrapper[] pkColumns = this.primaryKeyColumns_(); + public DTPColumnWrapper getPrimaryKeyColumn() { + DTPColumnWrapper[] pkColumns = this.getPrimaryKeyColumns(); if (pkColumns.length != 1) { throw new IllegalStateException("multiple primary key columns: " + pkColumns.length); //$NON-NLS-1$ } return pkColumns[0]; } - private synchronized DTPColumnWrapper[] primaryKeyColumns_() { + private synchronized DTPColumnWrapper[] getPrimaryKeyColumns() { if (this.primaryKeyColumns == null) { this.primaryKeyColumns = this.buildPrimaryKeyColumns(); } @@ -218,39 +175,35 @@ final class DTPTableWrapper // no PK was defined return EMPTY_COLUMNS; } - List<org.eclipse.datatools.modelbase.sql.tables.Column> pkColumns = this.columns(pk); + List<org.eclipse.datatools.modelbase.sql.tables.Column> pkColumns = this.getColumns(pk); DTPColumnWrapper[] result = new DTPColumnWrapper[pkColumns.size()]; for (int i = result.length; i-- > 0;) { - result[i] = this.column(pkColumns.get(i)); + result[i] = this.getColumn(pkColumns.get(i)); } return result; } // minimize scope of suppressed warnings @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.tables.Column> columns(PrimaryKey pk) { + private List<org.eclipse.datatools.modelbase.sql.tables.Column> getColumns(PrimaryKey pk) { return pk.getMembers(); } public int primaryKeyColumnsSize() { - return this.primaryKeyColumns_().length; + return this.getPrimaryKeyColumns().length; } - public boolean primaryKeyColumnsContains(Column column) { - return CollectionTools.contains(this.primaryKeyColumns_(), column); + boolean primaryKeyColumnsContains(Column column) { + return CollectionTools.contains(this.getPrimaryKeyColumns(), column); } // ***** foreignKeys public Iterator<ForeignKey> foreignKeys() { - return new ArrayIterator<ForeignKey>(this.foreignKeys_()); - } - - private Iterator<DTPForeignKeyWrapper> foreignKeyWrappers() { - return new ArrayIterator<DTPForeignKeyWrapper>(this.foreignKeys_()); + return new ArrayIterator<ForeignKey>(this.getForeignKeys()); } - private synchronized DTPForeignKeyWrapper[] foreignKeys_() { + private synchronized DTPForeignKeyWrapper[] getForeignKeys() { if (this.foreignKeys == null) { this.foreignKeys = this.buildForeignKeys(); } @@ -261,7 +214,7 @@ final class DTPTableWrapper if ( ! (this.dtpTable instanceof BaseTable)) { return EMPTY_FOREIGN_KEYS; } - List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> dtpForeignKeys = this.dtpForeignKeys(); + List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> dtpForeignKeys = this.getDTPForeignKeys(); DTPForeignKeyWrapper[] result = new DTPForeignKeyWrapper[dtpForeignKeys.size()]; for (int i = result.length; i-- > 0;) { result[i] = new DTPForeignKeyWrapper(this, dtpForeignKeys.get(i)); @@ -270,24 +223,92 @@ final class DTPTableWrapper } @SuppressWarnings("unchecked") - private List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> dtpForeignKeys() { + private List<org.eclipse.datatools.modelbase.sql.constraints.ForeignKey> getDTPForeignKeys() { return ((BaseTable) this.dtpTable).getForeignKeys(); } public int foreignKeysSize() { - return this.foreignKeys_().length; + return this.getForeignKeys().length; } - public boolean foreignKeyBaseColumnsContains(Column column) { - for (Iterator<DTPForeignKeyWrapper> stream = this.foreignKeyWrappers(); stream.hasNext(); ) { - DTPForeignKeyWrapper foreignKey = stream.next(); - if (foreignKey.baseColumnsContains(column)) { + /** + * return whether the specified column is a base column for at least one + * of the the table's foreign keys + */ + boolean foreignKeyBaseColumnsContains(Column column) { + for (DTPForeignKeyWrapper fkWrapper : this.getForeignKeys()) { + if (fkWrapper.baseColumnsContains(column)) { return true; } } return false; } + // ***** join table + + public boolean isPossibleJoinTable() { + if (this.getForeignKeys().length != 2) { + return false; // the table must have exactly 2 foreign keys + } + for (Column column : this.getColumns()) { + if ( ! this.foreignKeyBaseColumnsContains(column)) { + return false; // all the table's columns must belong to one (or both) of the 2 foreign keys + } + } + return true; + } + + /** + * If the table name is FOO_BAR and it joins tables FOO and BAR, + * return the foreign key to FOO; + * if the table name is BAR_FOO and it joins tables FOO and BAR, + * return the foreign key to BAR; + * otherwise simply return the first foreign key in the array. + */ + public ForeignKey getJoinTableOwningForeignKey() { + ForeignKey fk0 = this.getForeignKeys()[0]; + String name0 = fk0.getReferencedTable().getName(); + + ForeignKey fk1 = this.getForeignKeys()[1]; + String name1 = fk1.getReferencedTable().getName(); + + return this.getName().equals(name1 + '_' + name0) ? fk1 : fk0; + } + + public ForeignKey getJoinTableNonOwningForeignKey() { + ForeignKey fk0 = this.getForeignKeys()[0]; + ForeignKey fk1 = this.getForeignKeys()[1]; + ForeignKey ofk = this.getJoinTableOwningForeignKey(); + return (ofk == fk0) ? fk1 : fk0; + } + + /** + * Hmmm.... + * We might want to go to the platform to allow a vendor-specific + * comparison here; + * but, since all the names are coming directly from the database + * (i.e. there are no conversions to Java identifiers etc.), it seems + * like we can just compare them directly and ignore case-sensitivity + * issues.... ~bjv + */ + public boolean joinTableNameIsDefault() { + return this.getName().equals(this.buildDefaultJoinTableName()); + } + + private String buildDefaultJoinTableName() { + return this.getJoinTableOwningTable().getName() + + '_' + + this.getJoinTableNonOwningTable().getName(); + } + + private Table getJoinTableOwningTable() { + return this.getJoinTableOwningForeignKey().getReferencedTable(); + } + + private Table getJoinTableNonOwningTable() { + return this.getJoinTableNonOwningForeignKey().getReferencedTable(); + } + // ********** Comparable implementation ********** @@ -302,50 +323,94 @@ final class DTPTableWrapper return this.dtpTable == table; } - boolean isCaseSensitive() { - return this.schema.isCaseSensitive(); + /** + * return the table for the specified DTP table + */ + DTPTableWrapper getTable(org.eclipse.datatools.modelbase.sql.tables.Table table) { + // try to short-circuit the search + return this.wraps(table) ? this : this.getSchema().getTable(table); } - DTPTableWrapper table(org.eclipse.datatools.modelbase.sql.tables.Table table) { - return this.schema.table(table); - } - DTPDatabaseWrapper database() { - return this.schema.database(); + // ********** listening ********** + + @Override + synchronized void startListening() { + if (this.foreignKeys != null) { + this.startForeignKeys(); + } + if (this.columns != null) { + this.startColumns(); + } + super.startListening(); } + private void startForeignKeys() { + for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) { + foreignKey.startListening(); + } + } - // ********** disposal ********** + private void startColumns() { + for (DTPColumnWrapper column : this.columns) { + column.startListening(); + } + } @Override - synchronized void dispose() { - this.dispose_(); - super.dispose(); + synchronized void stopListening() { + if (this.foreignKeys != null) { + this.stopForeignKeys(); + } + if (this.columns != null) { + this.stopColumns(); + } + super.stopListening(); } - private void dispose_() { - this.disposeForeignKeys(); - // the table does not "contain" the pk columns, so no need to forward #dispose() - this.primaryKeyColumns = null; - this.disposeColumns(); + private void stopForeignKeys() { + for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) { + foreignKey.stopListening(); + } } - private void disposeForeignKeys() { - if (this.foreignKeys != null) { - for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) { - foreignKey.dispose(); - } - this.foreignKeys = null; + private void stopColumns() { + for (DTPColumnWrapper column : this.columns) { + column.stopListening(); } } - private void disposeColumns() { + + // ********** clear ********** + + @Override + void clear() { + if (this.foreignKeys != null) { + this.clearForeignKeys(); + } + + // the table does not "contain" the pk columns, so no need to forward #clear() + this.primaryKeyColumns = null; + if (this.columns != null) { - for (DTPColumnWrapper column : this.columns) { - column.dispose(); - } - this.columns = null; + this.clearColumns(); + } + } + + private void clearForeignKeys() { + this.stopForeignKeys(); + for (DTPForeignKeyWrapper foreignKey : this.foreignKeys) { + foreignKey.clear(); + } + this.foreignKeys = null; + } + + private void clearColumns() { + this.stopColumns(); + for (DTPColumnWrapper column : this.columns) { + column.clear(); } + this.columns = null; } } diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPWrapper.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPWrapper.java deleted file mode 100644 index cbe702a597..0000000000 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/DTPWrapper.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.db.internal; - -import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; -import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObjectListener; -import org.eclipse.datatools.connectivity.sqm.core.rte.RefreshManager; -import org.eclipse.jpt.utility.internal.StringTools; - -/** - * DTP Catalog Object Wrapper base class - */ -abstract class DTPWrapper - implements ConnectionProfileHolder -{ - // we need a way to get to the connection profile - private final ConnectionProfileHolder connectionProfileHolder; - - // listen for the "catalog object" being refreshed - private final ICatalogObjectListener catalogObjectListener; - - // we only listen to "live" connections - private final boolean connectionIsLive; - - // listen for this to refresh - final ICatalogObject catalogObject; - - - DTPWrapper(ConnectionProfileHolder connectionProfileHolder, Object dtpObject) { - super(); - this.connectionProfileHolder = connectionProfileHolder; - this.connectionIsLive = this.getConnectionProfile().isConnected(); - if (this.connectionIsLive) { - this.catalogObject = (ICatalogObject) dtpObject; - this.catalogObjectListener = this.buildCatalogObjectListener(); - RefreshManager.getInstance().AddListener(this.catalogObject, this.catalogObjectListener); - } else { - this.catalogObject = null; - this.catalogObjectListener = null; - } - } - - private ICatalogObjectListener buildCatalogObjectListener() { - return new ICatalogObjectListener() { - public void notifyChanged(ICatalogObject dmElement, int eventType) { - if (dmElement == DTPWrapper.this.catalogObject) { - DTPWrapper.this.catalogObjectChanged(eventType); - } - } - }; - } - - // typically, notify the connection profile something has changed - abstract void catalogObjectChanged(int eventType); - - public DTPConnectionProfileWrapper getConnectionProfile() { - return this.connectionProfileHolder.getConnectionProfile(); - } - - void dispose() { - if (this.connectionIsLive) { - RefreshManager.getInstance().removeListener(this.catalogObject, this.catalogObjectListener); - } - } - - // all the subclasses can implement this method - abstract String getName(); - - @Override - public String toString() { - return StringTools.buildToStringFor(this, this.getName()); - } - -} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/InternalDatabase.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/InternalDatabase.java deleted file mode 100644 index aa61c6043f..0000000000 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/InternalDatabase.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * 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.db.internal; - -import org.eclipse.jpt.db.Database; - -/** - * "internal" database - */ -interface InternalDatabase extends Database { - DTPCatalogWrapper getDefaultCatalog(); - void dispose(); -} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullConnectionProfile.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullConnectionProfile.java deleted file mode 100644 index 5673dfb5d9..0000000000 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullConnectionProfile.java +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.db.internal; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jpt.db.Catalog; -import org.eclipse.jpt.db.ConnectionListener; -import org.eclipse.jpt.db.ConnectionProfile; -import org.eclipse.jpt.db.Database; -import org.eclipse.jpt.db.Schema; -import org.eclipse.jpt.utility.internal.ClassTools; - -/** - * "null" connection profile - */ -final class NullConnectionProfile - implements ConnectionProfile -{ - private static final String EMPTY_STRING = ""; //$NON-NLS-1$ - - - // ********** singleton ********** - - private static final NullConnectionProfile INSTANCE = new NullConnectionProfile(); - - static ConnectionProfile instance() { - return INSTANCE; - } - - /** - * 'private' to ensure singleton - */ - private NullConnectionProfile() { - super(); - } - - - // ********** ConnectionProfile implementation ********** - - public void connect() { - // do nothing - } - - public void disconnect() { - // do nothing - } - - public IStatus saveWorkOfflineData() { - return Status.CANCEL_STATUS; - } - - public IStatus workOffline() { - return Status.CANCEL_STATUS; - } - - public Database getDatabase() { - return NullDatabase.instance(); - } - - public String getName() { - return ClassTools.shortClassNameForObject(this); - } - - public String getDatabaseName() { - return EMPTY_STRING; - } - - public String getDatabaseProduct() { - return EMPTY_STRING; - } - - public String getDatabaseVendor() { - return EMPTY_STRING; - } - - public String getDatabaseVersion() { - return EMPTY_STRING; - } - - public String getUserName() { - return EMPTY_STRING; - } - - public String getUserPassword() { - return EMPTY_STRING; - } - - public String getDriverClassName() { - return EMPTY_STRING; - } - - public String getUrl() { - return EMPTY_STRING; - } - - public String getInstanceID() { - return EMPTY_STRING; - } - - public String getProviderID() { - return EMPTY_STRING; - } - - public String getDriverDefinitionID() { - return EMPTY_STRING; - } - - public String getDriverJarList() { - return EMPTY_STRING; - } - - public boolean isActive() { - return false; - } - - public boolean isWorkingOffline() { - return false; - } - - public boolean isConnected() { - return false; - } - - public boolean supportsWorkOfflineMode() { - return false; - } - - public boolean canWorkOffline() { - return false; - } - - public void addConnectionListener( ConnectionListener listener) { - // do nothing - } - - public void removeConnectionListener( ConnectionListener listener) { - // do nothing - } - - public Schema getDefaultSchema() { - return null; - } - - public Catalog getDefaultCatalog() { - return null; - } - - public boolean isNull() { - return true; - } - - - // ********** Comparable implementation ********** - - public int compareTo(ConnectionProfile o) { - throw new UnsupportedOperationException("the \"null\" connection profile should not be in a sorted list"); //$NON-NLS-1$ - } - - - // ********** Object overrides ********** - - @Override - public String toString() { - return ClassTools.toStringClassNameForObject(this); - } - -} diff --git a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullDatabase.java b/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullDatabase.java deleted file mode 100644 index 8ff4139cfd..0000000000 --- a/jpa/plugins/org.eclipse.jpt.db/src/org/eclipse/jpt/db/internal/NullDatabase.java +++ /dev/null @@ -1,148 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.db.internal; - -import java.util.Iterator; - -import org.eclipse.datatools.connectivity.sqm.core.definition.DatabaseDefinition; -import org.eclipse.jpt.db.Catalog; -import org.eclipse.jpt.db.Database; -import org.eclipse.jpt.db.Schema; -import org.eclipse.jpt.utility.internal.ClassTools; -import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; - -/** - * "null" database - * This is used when the connection profile is inactive (i.e. it is neither - * connected to the database nor working off-line). - */ -final class NullDatabase - implements InternalDatabase -{ - private static final String EMPTY_STRING = ""; //$NON-NLS-1$ - - - // ********** singleton ********** - - private static final NullDatabase INSTANCE = new NullDatabase(); - - static synchronized InternalDatabase instance() { - return INSTANCE; - } - - /** - * 'private' to ensure singleton - */ - private NullDatabase() { - super(); - } - - - // ********** Database implementation ********** - - public String getName() { - return ClassTools.shortClassNameForObject(this); - } - - public String getVendor() { - return EMPTY_STRING; - } - - public String getVersion() { - return EMPTY_STRING; - } - - public boolean isCaseSensitive() { - return false; - } - - public DatabaseDefinition getDtpDefinition() { - return null; - } - - // ***** catalogs - - public boolean supportsCatalogs() { - return false; - } - - public Iterator<Catalog> catalogs() { - return EmptyIterator.<Catalog>instance(); - } - - public int catalogsSize() { - return 0; - } - - public Iterator<String> catalogNames() { - return EmptyIterator.<String>instance(); - } - - public boolean containsCatalogNamed(String name) { - return false; - } - - public Catalog catalogNamed(String name) { - return null; - } - - public String defaultCatalogName() { - return EMPTY_STRING; - } - - public DTPCatalogWrapper getDefaultCatalog() { - return null; - } - - // ***** schemata - - public Iterator<Schema> schemata() { - return EmptyIterator.<Schema>instance(); - } - - public int schemataSize() { - return 0; - } - - public Iterator<String> schemaNames() { - return EmptyIterator.<String>instance(); - } - - public boolean containsSchemaNamed(String name) { - return false; - } - - public Schema schemaNamed(String name) { - return null; - } - - - // ********** InternalDatabase implementation ********** - - public void dispose() { - // do nothing - } - - - // ********** Comparable implementation ********** - - public int compareTo(Database o) { - throw new UnsupportedOperationException("the \"null\" database should not be in a sorted list"); //$NON-NLS-1$ - } - - - // ********** Object overrides ********** - - @Override - public String toString() { - return ClassTools.toStringClassNameForObject(this); - } - -} diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/ddlgen/EclipseLinkDDLGenerator.java b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/ddlgen/EclipseLinkDDLGenerator.java index 5206c1bb60..3fcb41bd8a 100644 --- a/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/ddlgen/EclipseLinkDDLGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.eclipselink.core/src/org/eclipse/jpt/eclipselink/core/internal/ddlgen/EclipseLinkDDLGenerator.java @@ -100,10 +100,6 @@ public class EclipseLinkDDLGenerator return this.project.getJpaPlatform(); } - protected ConnectionProfile getConnectionProfile() { - return this.project.getConnectionProfile(); - } - protected ILaunch getLaunch() { return this.launch; } @@ -198,7 +194,12 @@ public class EclipseLinkDDLGenerator } private IPath buildJdbcJarPath() { - return new Path(this.project.getConnectionProfile().getDriverJarList()); + return new Path(this.getProjectConnectionDriverJarList()); + } + + private String getProjectConnectionDriverJarList() { + ConnectionProfile cp = this.project.getConnectionProfile(); + return (cp == null) ? "" : cp.getDriverJarList(); //$NON-NLS-1$ } private IPath buildBootstrapJarPath() { @@ -342,23 +343,23 @@ public class EclipseLinkDDLGenerator } private void buildLoginProperties(Properties properties) { - ConnectionProfile profile = this.getConnectionProfile(); + ConnectionProfile cp = this.project.getConnectionProfile(); this.putProperty(properties, Connection.ECLIPSELINK_BIND_PARAMETERS, "false"); this.putProperty(properties, Connection.ECLIPSELINK_DRIVER, - profile.getDriverClassName()); + (cp == null) ? "" : cp.getDriverClassName()); this.putProperty(properties, Connection.ECLIPSELINK_URL, - profile.getUrl()); + (cp == null) ? "" : cp.getURL()); this.putProperty(properties, Connection.ECLIPSELINK_USER, - profile.getUserName()); + (cp == null) ? "" : cp.getUserName()); this.putProperty(properties, Connection.ECLIPSELINK_PASSWORD, - profile.getUserPassword()); + (cp == null) ? "" : cp.getUserPassword()); this.putProperty(properties, Logging.ECLIPSELINK_LEVEL, LoggingLevel.FINEST); diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/connection/JdbcConnectionPropertiesComposite.java b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/connection/JdbcConnectionPropertiesComposite.java index 2bbe6c9c0a..d4b856724c 100644 --- a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/connection/JdbcConnectionPropertiesComposite.java +++ b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/connection/JdbcConnectionPropertiesComposite.java @@ -11,6 +11,7 @@ package org.eclipse.jpt.eclipselink.ui.internal.connection; import java.util.Comparator; import java.util.Iterator; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -20,6 +21,7 @@ import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.ConnectionProfileFactory; import org.eclipse.jpt.db.JptDbPlugin; import org.eclipse.jpt.eclipselink.core.internal.context.connection.Connection; import org.eclipse.jpt.eclipselink.ui.internal.EclipseLinkUiMessages; @@ -31,6 +33,7 @@ import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.dialogs.FilteredItemsSelectionDialog; /** @@ -146,41 +149,55 @@ public class JdbcConnectionPropertiesComposite extends AbstractPane<Connection> new JdbcBindParametersComposite(this, container); } - private void promptConnection() { + void promptConnection() { - ConnecionSelectionDialog dialog = new ConnecionSelectionDialog(); + ConnectionSelectionDialog dialog = new ConnectionSelectionDialog(); - if (dialog.open() == IDialogConstants.OK_ID) { + if (dialog.open() != IDialogConstants.OK_ID) { + return; + } - String name = (String) dialog.getResult()[0]; - ConnectionProfile profile = JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(name); + String name = (String) dialog.getResult()[0]; + ConnectionProfile cp = this.getConnectionProfileFactory().buildConnectionProfile(name); - Connection connection = subject(); - connection.setUrl(profile.getUrl()); - connection.setUser(profile.getUserName()); - connection.setPassword(profile.getUserPassword()); - connection.setDriver(profile.getDriverClassName()); - } + Connection connection = subject(); + connection.setUrl((cp == null) ? "" : cp.getURL()); + connection.setUser((cp == null) ? "" : cp.getUserName()); + connection.setPassword((cp == null) ? "" : cp.getUserPassword()); + connection.setDriver((cp == null) ? "" : cp.getDriverClassName()); + } + + ConnectionProfileFactory getConnectionProfileFactory() { + // we allow the user to select any connection profile and simply + // take the settings from it (user, password, etc.) and give them + // to the EclipseLink connection, so we go + // to the db plug-in directly to get the factory + return JptDbPlugin.instance().getConnectionProfileFactory(); + } + + // broaden access a bit + Shell shell_() { + return this.shell(); } /** * This dialog shows the list of possible connection names and lets the user * the option to filter them using a search field. */ - protected class ConnecionSelectionDialog extends FilteredItemsSelectionDialog { + protected class ConnectionSelectionDialog extends FilteredItemsSelectionDialog { /** * Creates a new <code>MappingSelectionDialog</code>. */ - private ConnecionSelectionDialog() { - super(JdbcConnectionPropertiesComposite.this.shell(), false); + protected ConnectionSelectionDialog() { + super(JdbcConnectionPropertiesComposite.this.shell_(), false); setMessage(EclipseLinkUiMessages.JdbcConnectionPropertiesComposite_ConnectionDialog_Message); setTitle(EclipseLinkUiMessages.JdbcConnectionPropertiesComposite_ConnectionDialog_Title); setListLabelProvider(buildLabelProvider()); setDetailsLabelProvider(buildLabelProvider()); } - private ILabelProvider buildLabelProvider() { + protected ILabelProvider buildLabelProvider() { return new LabelProvider() { @Override public Image getImage(Object element) { @@ -222,8 +239,8 @@ public class JdbcConnectionPropertiesComposite extends AbstractPane<Connection> try { // Add the connection names to the dialog - for (Iterator<String> names = JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNames(); names.hasNext(); ) { - provider.add(names.next(), itemsFilter); + for (Iterator<String> stream = this.connectionProfileNames(); stream.hasNext(); ) { + provider.add(stream.next(), itemsFilter); } } finally { @@ -231,6 +248,10 @@ public class JdbcConnectionPropertiesComposite extends AbstractPane<Connection> } } + private Iterator<String> connectionProfileNames() { + return JdbcConnectionPropertiesComposite.this.getConnectionProfileFactory().connectionProfileNames(); + } + /* * (non-Javadoc) */ diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/EclipseLinkDDLGeneratorUi.java b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/EclipseLinkDDLGeneratorUi.java index 1ddf744d0f..2e80963ce9 100644 --- a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/EclipseLinkDDLGeneratorUi.java +++ b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/EclipseLinkDDLGeneratorUi.java @@ -72,7 +72,7 @@ public class EclipseLinkDDLGeneratorUi return; } - GenerateDDLWizard wizard = new GenerateDDLWizard(this.project, this.selection); + GenerateDDLWizard wizard = new GenerateDDLWizard(this.project); WizardDialog dialog = new WizardDialog(this.getCurrentShell(), wizard); dialog.create(); if(wizard.getPageCount() > 0) { diff --git a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/wizards/GenerateDDLWizard.java b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/wizards/GenerateDDLWizard.java index 84963eaf48..1f5be988d3 100644 --- a/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/wizards/GenerateDDLWizard.java +++ b/jpa/plugins/org.eclipse.jpt.eclipselink.ui/src/org/eclipse/jpt/eclipselink/ui/internal/ddlgen/wizards/GenerateDDLWizard.java @@ -9,13 +9,11 @@ *******************************************************************************/ package org.eclipse.jpt.eclipselink.ui.internal.ddlgen.wizards; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; 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.ui.internal.wizards.DatabaseReconnectWizardPage; +import org.eclipse.jpt.ui.internal.wizards.DatabaseConnectionWizardPage; /** * GenerateDDLWizard @@ -24,53 +22,41 @@ public class GenerateDDLWizard extends Wizard { private JpaProject jpaProject; - private IStructuredSelection selection; + private DatabaseConnectionWizardPage dbSettingsPage; - private DatabaseReconnectWizardPage dbSettingsPage; - - public GenerateDDLWizard(JpaProject jpaProject, IStructuredSelection selection) { + public GenerateDDLWizard(JpaProject jpaProject) { super(); this.jpaProject = jpaProject; - this.selection = selection; - this.setWindowTitle("DDL Generation"); + this.setWindowTitle("DDL Generation"); // TODO } + @Override public void addPages() { super.addPages(); - if ( ! this.jpaProjectHasConnection()) { - this.dbSettingsPage = new DatabaseReconnectWizardPage(this.jpaProject); + if (this.getProjectConnectionProfile() == null) { + this.dbSettingsPage = new DatabaseConnectionWizardPage(this.jpaProject); this.addPage(this.dbSettingsPage); } } - @SuppressWarnings("restriction") + @Override public boolean performFinish() { - String name = getProjectConnectionProfile().getName(); - if ( ! this.jpaProjectHasConnection()) { - - String connectionProfileName = this.dbSettingsPage.getSelectedConnectionProfileName(); - ConnectionProfile profile = JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed( connectionProfileName); - if( profile.isNull()) { - this.dbSettingsPage.clearConnectionProfileName(); - return false; - } - this.setProjectConnectionProfileName(connectionProfileName); + if (this.getProjectConnectionProfile() != null) { + return true; + } + ConnectionProfile cp = this.dbSettingsPage.getSelectedConnectionProfile(); + if (cp == null) { + return false; } + this.setProjectConnectionProfileName(cp.getName()); return true; } - public boolean canFinish() { - boolean canFinish = true; - if ( ! this.dbSettingsPage.isPageComplete()) { - canFinish = false; - } - return canFinish; + @Override + public boolean canFinish() { + return this.dbSettingsPage.isPageComplete(); } - private boolean jpaProjectHasConnection() { - return ! this.getProjectConnectionProfile().isNull(); - } - private ConnectionProfile getProjectConnectionProfile() { return this.jpaProject.getConnectionProfile(); } diff --git a/jpa/plugins/org.eclipse.jpt.gen/.classpath b/jpa/plugins/org.eclipse.jpt.gen/.classpath index 304e86186a..8f257414e6 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/.classpath +++ b/jpa/plugins/org.eclipse.jpt.gen/.classpath @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="property_files"/> <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 3f44799ab8..09b0d828ae 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF +++ b/jpa/plugins/org.eclipse.jpt.gen/META-INF/MANIFEST.MF @@ -10,6 +10,5 @@ Export-Package: org.eclipse.jpt.gen.internal; x-friends:="org.eclipse.jpt.ui" 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.1.1,2.0.0)", - org.eclipse.jpt.core;bundle-version="[2.0.0,3.0.0)" + org.eclipse.jpt.db;bundle-version="[1.1.1,2.0.0)" Bundle-RequiredExecutionEnvironment: J2SE-1.5 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 new file mode 100644 index 0000000000..03e8908d0e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/property_files/jpt_gen.properties @@ -0,0 +1,13 @@ +################################################################################ +# 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 +################################################################################ + +PackageGenerator_taskName=Generate Entities +GenScope_taskName=Build Database Model +EntityGenerator_taskName=Generate Entity: {0} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenTools.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenTools.java new file mode 100644 index 0000000000..40f595db55 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenTools.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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.internal; + +import java.util.Collection; + +import org.eclipse.jpt.utility.internal.NameTools; +import org.eclipse.jpt.utility.internal.StringTools; + +/** + * Utility methods for entity generation. + */ +public class EntityGenTools { + + /** + * Convert the specified (database) identifier to a unique "Java style" + * class name. + * @see #convertToUniqueJavaStyleIdentifier(String, boolean, Collection) + */ + public static String convertToUniqueJavaStyleClassName(String identifier, Collection<String> classNames) { + return convertToUniqueJavaStyleIdentifier(identifier, true, classNames); + } + + /** + * Convert the specified (database) identifier to a unique "Java style" + * attribute (field/property) name. + * @see #convertToUniqueJavaStyleIdentifier(String, boolean, Collection) + */ + public static String convertToUniqueJavaStyleAttributeName(String identifier, Collection<String> attributeNames) { + return convertToUniqueJavaStyleIdentifier(identifier, false, attributeNames); + } + + /** + * Convert the specified (database) identifier to a unique "Java style" + * identifier: + * - if the identifier is all-caps, convert underscores to "camel case" + * - if the identifier is not all-caps, leave it unchanged (except, possibly, for the first letter) + * - convert to a legal Java identifier + * - eliminate illegal characters + * - if the result is a reserved word, modify it slightly + * If the result is already one of the specified existing identifiers + * (ignoring case so we don't have filename collisions on Windows), + * modify it slightly again. + * "FOO" => "Foo" or "foo" + * "FOO_BAR" => "FooBar" or "fooBar" + * "PACKAGE" => "Package" or "package_" + */ + public static String convertToUniqueJavaStyleIdentifier(String identifier, boolean capitalizeFirstLetter, Collection<String> identifiers) { + String result = identifier; + if (StringTools.stringIsUppercase(result)) { + // leave mixed case identifiers alone? + result = StringTools.convertUnderscoresToCamelCase(result, capitalizeFirstLetter); + } else { + if (capitalizeFirstLetter) { + result = StringTools.capitalize(result); + } else { + result = StringTools.uncapitalize(result); + } + } + result = NameTools.convertToJavaIdentifier(result); + // assume that converting to a unique name will not result in a Java reserved word + // (since no Java reserved words end with a number) + result = NameTools.uniqueNameForIgnoreCase(result, identifiers); + return result; + } + + + // ********** constructor ********** + + /** + * Suppress default constructor, ensuring non-instantiability. + */ + private EntityGenTools() { + super(); + throw new UnsupportedOperationException(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java index e8724927a9..f5c434564a 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/EntityGenerator.java @@ -22,25 +22,23 @@ import java.util.Set; import java.util.TreeSet; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jpt.core.resource.java.JPA; import org.eclipse.jpt.db.Column; import org.eclipse.jpt.db.ForeignKey; import org.eclipse.jpt.db.Table; import org.eclipse.jpt.utility.JavaType; +import org.eclipse.jpt.utility.internal.BooleanHolder; import org.eclipse.jpt.utility.internal.IndentingPrintWriter; +import org.eclipse.jpt.utility.internal.NameTools; import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.osgi.util.NLS; -// TODO handle table names that are illegal class names -// TODO handle table names that are illegal file names -// TODO handle column names that are illegal field/method names -// TODO format code per preferences -// TODO organize imports per preferences -// TODO prompt user to overwrite existing classes +// TODO format generated code per preferences +// TODO organize generated imports per preferences /** * This generator will generate an entity for a table. */ @@ -49,98 +47,90 @@ public class EntityGenerator { private final IPackageFragment packageFragment; private final GenTable genTable; private final String entityClassName; - private final OverwriteConfirmer overwriteConfirmer; - private final IProgressMonitor monitor; private final String pkClassName; // ********** public API ********** - static void generateEntity(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { + static void generateEntity( + Config config, + IPackageFragment packageFragment, + GenTable genTable, + IProgressMonitor progressMonitor + ) { if ((config == null) || (packageFragment == null) || (genTable == null)) { throw new NullPointerException(); } - new EntityGenerator(config, packageFragment, genTable, overwriteConfirmer, monitor).generateEntity(); + new EntityGenerator(config, packageFragment, genTable).generateEntity(progressMonitor); } // ********** constructor/initialization ********** - private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { + private EntityGenerator(Config config, IPackageFragment packageFragment, GenTable genTable) { super(); this.config = config; this.packageFragment = packageFragment; this.genTable = genTable; - this.entityClassName = this.fullyQualify(this.entityName()); - this.overwriteConfirmer = overwriteConfirmer; - this.monitor = monitor; - this.pkClassName = this.entityClassName + "PK"; // hack + this.entityClassName = this.fullyQualify(this.getEntityName()); + this.pkClassName = this.entityClassName + '.' + config.getPrimaryKeyMemberClassName(); } // ********** code gen ********** - private void generateEntity() { - int totalWork = pkClassIsGenerated() ? 40 : 20; + private void generateEntity(IProgressMonitor progressMonitor) { try { - this.monitor.beginTask("", totalWork); - this.generateEntity_(); + this.generateEntity_(progressMonitor); } catch (JavaModelException ex) { throw new RuntimeException(ex); } - finally { - this.monitor.done(); - } - } - - private void generateEntity_() throws JavaModelException { - // build the body source first so we can gather up the import statements - this.generateSourceFile(this.entityClassName, this.entityName() + ".java", this.buildSource(this.buildBodySource())); - if (this.pkClassIsGenerated()) { - this.generateSourceFile(this.pkClassName, this.pkName() + ".java", this.buildSource(this.buildPKBodySource())); - } - } - private void generateSourceFile(String className, String fileName, String source) throws JavaModelException { + private void generateEntity_(IProgressMonitor progressMonitor) throws JavaModelException { + SubMonitor sm = SubMonitor.convert(progressMonitor, this.buildTaskName(), 100); + String fileName = this.getEntityName() + ".java"; //$NON-NLS-1$ + String source = this.buildSource(); + sm.worked(20); try { - this.packageFragment.createCompilationUnit(fileName, source, false, new SubProgressMonitor(this.monitor, 10)); + this.packageFragment.createCompilationUnit(fileName, source, false, sm.newChild(40)); } catch (JavaModelException ex) { if (ex.getJavaModelStatus().getCode() == IJavaModelStatusConstants.NAME_COLLISION) { - if (this.overwriteConfirmer.overwrite(className)) { - this.packageFragment.createCompilationUnit(fileName, source, true, new SubProgressMonitor(this.monitor, 0)); + if (this.config.getOverwriteConfirmer().overwrite(this.entityClassName)) { + this.packageFragment.createCompilationUnit(fileName, source, true, sm.newChild(40)); } } else { throw ex; } } + sm.setWorkRemaining(0); + } + + private String buildTaskName() { + return NLS.bind(JptGenMessages.EntityGenerator_taskName, this.getEntityName()); } /** * build the "body" source first; then build the "package" and "imports" source * and concatenate the "body" source to it */ - private String buildSource(BodySource bodySource) { - StringWriter sw = new StringWriter(bodySource.length() + 1000); + private String buildSource() { + // build the body source first so we can gather up the import statements + BodySource bodySource = this.buildBodySource(); + + StringWriter sw = new StringWriter(bodySource.length() + 2000); PrintWriter pw = new PrintWriter(sw); this.printPackageAndImportsOn(pw, bodySource); - pw.print(bodySource.source()); - this.monitor.worked(10); + pw.print(bodySource.getSource()); return sw.toString(); } private BodySource buildBodySource() { - EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.entityClassName); + EntitySourceWriter pw = new EntitySourceWriter(this.getPackageName(), this.entityClassName); this.printBodySourceOn(pw); return pw; } - private BodySource buildPKBodySource() { - EntitySourceWriter pw = new EntitySourceWriter(this.packageName(), this.pkClassName); - this.printPrimaryKeyClassOn(pw); - return pw; - } - private void printBodySourceOn(EntitySourceWriter pw) { this.printClassDeclarationOn(pw); @@ -151,36 +141,43 @@ public class EntityGenerator { this.printEntityOneToManyFieldsOn(pw); this.printEntityOwnedManyToManyFieldsOn(pw); this.printEntityNonOwnedManyToManyFieldsOn(pw); - this.printSerialVersionUID(pw); + this.printSerialVersionUIDFieldOn(pw); pw.println(); - this.printZeroArgumentConstructorOn(this.entityName(), this.config.methodVisibility(), pw); + this.printZeroArgumentConstructorOn(this.getEntityName(), this.config.getMethodVisibilityClause(), pw); if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) { - this.printEntityPrimaryKeyGettersAndSettersOn(pw); - this.printEntityNonPrimaryKeyBasicGettersAndSettersOn(pw); - this.printEntityManyToOneGettersAndSettersOn(pw); - this.printEntityOneToManyGettersAndSettersOn(pw); - this.printEntityOwnedManyToManyGettersAndSettersOn(pw); - this.printEntityNonOwnedManyToManyGettersAndSettersOn(pw); + this.printEntityPrimaryKeyPropertiesOn(pw); + this.printEntityNonPrimaryKeyBasicPropertiesOn(pw); + this.printEntityManyToOnePropertiesOn(pw); + this.printEntityOneToManyPropertiesOn(pw); + this.printEntityOwnedManyToManyPropertiesOn(pw); + this.printEntityNonOwnedManyToManyPropertiesOn(pw); + } + + if (this.primaryKeyClassIsRequired()) { + this.printPrimaryKeyClassOn(pw); } pw.undent(); pw.print('}'); - pw.println(); + pw.println(); // EOF } + + // ********** class declaration ********** + private void printClassDeclarationOn(EntitySourceWriter pw) { this.printEntityAnnotationOn(pw); this.printTableAnnotationOn(pw); this.printIdClassAnnotationOn(pw); - pw.print("public class "); + pw.print("public class "); //$NON-NLS-1$ pw.printTypeDeclaration(this.entityClassName); if (config.serializable()) { - pw.print(" implements "); + pw.print(" implements "); //$NON-NLS-1$ pw.printTypeDeclaration(Serializable.class.getName()); } - pw.print(" {"); + pw.print(" {"); //$NON-NLS-1$ pw.println(); } @@ -190,27 +187,32 @@ public class EntityGenerator { } private void printTableAnnotationOn(EntitySourceWriter pw) { - if ( ! this.table().matchesShortJavaClassName(this.entityName())) { - pw.printAnnotation(JPA.TABLE); - pw.print("(name=\""); - pw.print(this.table().getName()); - pw.print("\")"); - pw.println(); + String tableName = this.config.getDatabaseAnnotationNameBuilder().buildTableAnnotationName(this.getEntityName(), this.getTable()); + if (tableName == null) { + return; // the default table name is OK } + pw.printAnnotation(JPA.TABLE); + pw.print("(name="); //$NON-NLS-1$ + pw.printStringLiteral(tableName); + pw.print(')'); + pw.println(); } private void printIdClassAnnotationOn(EntitySourceWriter pw) { - if (this.pkClassIsGenerated() && this.config.generateIdClassForCompoundPK()) { + if (this.primaryKeyClassIsRequired() && this.config.generateIdClassForCompoundPK()) { pw.printAnnotation(JPA.ID_CLASS); pw.print('('); - pw.printTypeDeclaration(pkClassName); - pw.print(".class)"); + pw.printTypeDeclaration(this.pkClassName); + pw.print(".class)"); //$NON-NLS-1$ pw.println(); } } + + // ********** primary key fields ********** + private void printEntityPrimaryKeyFieldsOn(EntitySourceWriter pw) { - if (this.pkClassIsGenerated() && this.config.generateEmbeddedIdForCompoundPK()) { + if (this.primaryKeyClassIsRequired() && this.config.generateEmbeddedIdForCompoundPK()) { this.printEntityEmbeddedIdPrimaryKeyFieldOn(pw); } else { this.printEntityReadOnlyPrimaryKeyFieldsOn(pw); @@ -223,94 +225,60 @@ public class EntityGenerator { pw.printAnnotation(JPA.EMBEDDED_ID); pw.println(); } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(this.pkClassName); - pw.print(' '); - pw.print(this.genTable.fieldNameForEmbeddedId()); - pw.print(';'); - pw.println(); - pw.println(); + this.printFieldOn(this.genTable.getAttributeNameForEmbeddedId(), this.pkClassName, pw); } private void printEntityReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) { - this.printReadOnlyPrimaryKeyFieldsOn(pw, true); // true=print ID annotation on fields + this.printPrimaryKeyFieldsOn(pw, true, true); // true=read-only; true=print ID annotation on fields + } + + private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) { + this.printPrimaryKeyFieldsOn(pw, false, true); // false=writable; true=print ID annotation on fields } - private void printReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw, boolean printIdAnnotation) { - for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) { - this.printReadOnlyPrimaryKeyFieldOn(stream.next(), pw, printIdAnnotation); + private void printPrimaryKeyFieldsOn(EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) { + for (Iterator<Column> stream = this.primaryKeyColumns(readOnly); stream.hasNext(); ) { + this.printPrimaryKeyFieldOn(stream.next(), pw, readOnly, printIdAnnotation); } } - // TODO if the field's type is java.util.Date, it needs @Temporal(DATE) + private Iterator<Column> primaryKeyColumns(boolean readOnly) { + return readOnly ? this.genTable.readOnlyPrimaryKeyColumns() : this.genTable.writablePrimaryKeyColumns(); + } + + // TODO if the field's type is java.util/sql.Date, it needs @Temporal(DATE) // TODO if the primary key is auto-generated, the field must be an integral type - private void printReadOnlyPrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) { - String fieldName = this.genTable.fieldNameFor(column); + private void printPrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) { + String fieldName = this.genTable.getAttributeNameFor(column); if (this.config.fieldAccessType()) { if (printIdAnnotation) { pw.printAnnotation(JPA.ID); pw.println(); } - if (column.matchesJavaFieldName(fieldName)) { - this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed + String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(fieldName, column); + if (readOnly) { + this.printReadOnlyColumnAnnotationOn(columnName, pw); } else { - this.printReadOnlyColumnAnnotationOn(column.getName(), pw); + this.printColumnAnnotationOn(columnName, pw); } } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(column.getPrimaryKeyJavaTypeDeclaration()); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printFieldOn(fieldName, column.getPrimaryKeyJavaTypeDeclaration(), pw); } private void printReadOnlyColumnAnnotationOn(String columnName, EntitySourceWriter pw) { pw.printAnnotation(JPA.COLUMN); - pw.print("(name=\""); - pw.print(columnName); - pw.print("\", insertable=false, updatable=false)"); - pw.println(); - } - - private void printReadOnlyColumnAnnotationOn(EntitySourceWriter pw) { - pw.printAnnotation(JPA.COLUMN); - pw.print("(insertable=false, updatable=false)"); + pw.print('('); + if (columnName != null) { + pw.print("name="); //$NON-NLS-1$ + pw.printStringLiteral(columnName); + pw.print(", "); //$NON-NLS-1$ + } + pw.print("insertable=false, updatable=false)"); //$NON-NLS-1$ pw.println(); } - private void printEntityWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) { - this.printWritablePrimaryKeyFieldsOn(pw, true); // true=print ID annotation on fields - } - private void printWritablePrimaryKeyFieldsOn(EntitySourceWriter pw, boolean printIdAnnotation) { - for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) { - this.printWritablePrimaryKeyFieldOn(stream.next(), pw, printIdAnnotation); - } - } - - // TODO if the field's type is java.util.Date, it needs @Temporal(DATE) - // TODO if the primary key is auto-generated, the field must be an integral type - private void printWritablePrimaryKeyFieldOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) { - String fieldName = this.genTable.fieldNameFor(column); - if (this.config.fieldAccessType()) { - if (printIdAnnotation) { - pw.printAnnotation(JPA.ID); - pw.println(); - } - if ( ! column.matchesJavaFieldName(fieldName)) { - this.printColumnAnnotationOn(column.getName(), pw); - } - } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(column.getPrimaryKeyJavaTypeDeclaration()); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); - } + // ********** basic fields ********** private void printEntityNonPrimaryKeyBasicFieldsOn(EntitySourceWriter pw) { for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) { @@ -319,33 +287,31 @@ public class EntityGenerator { } private void printEntityNonPrimaryKeyBasicFieldOn(Column column, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(column); + String fieldName = this.genTable.getAttributeNameFor(column); if (this.config.fieldAccessType()) { - if ( ! column.matchesJavaFieldName(fieldName)) { - this.printColumnAnnotationOn(column.getName(), pw); - } + String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(fieldName, column); + this.printColumnAnnotationOn(columnName, pw); } if (column.dataTypeIsLOB()) { pw.printAnnotation(JPA.LOB); pw.println(); } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(column.getJavaTypeDeclaration()); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printFieldOn(fieldName, column.getJavaTypeDeclaration(), pw); } private void printColumnAnnotationOn(String columnName, EntitySourceWriter pw) { - pw.printAnnotation(JPA.COLUMN); - pw.print("(name=\""); - pw.print(columnName); - pw.print("\")"); - pw.println(); + if (columnName != null) { // the column name is null if the default is OK + pw.printAnnotation(JPA.COLUMN); + pw.print("(name="); //$NON-NLS-1$ + pw.printStringLiteral(columnName); + pw.print(')'); + pw.println(); + } } + + // ********** many-to-one fields ********** + private void printEntityManyToOneFieldsOn(EntitySourceWriter pw) { for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) { this.printEntityManyToOneFieldOn(stream.next(), pw); @@ -353,44 +319,44 @@ public class EntityGenerator { } private void printEntityManyToOneFieldOn(ManyToOneRelation relation, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(relation); + String fieldName = this.genTable.getAttributeNameFor(relation); if (this.config.fieldAccessType()) { this.printManyToOneAnnotationOn(fieldName, relation, pw); } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName())); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printFieldOn(fieldName, this.fullyQualify(relation.getReferencedEntityName()), pw); } - private void printManyToOneAnnotationOn(String fieldName, ManyToOneRelation relation, EntitySourceWriter pw) { + private void printManyToOneAnnotationOn(String attributeName, ManyToOneRelation relation, EntitySourceWriter pw) { pw.printAnnotation(JPA.MANY_TO_ONE); pw.println(); - ForeignKey fk = relation.getForeignKey(); - if (fk.defaultMatchesJavaFieldName(fieldName)) { - return; // no JoinColumn annotation needed - } - if (fk.referencesSingleColumnPrimaryKey()) { - pw.printAnnotation(JPA.JOIN_COLUMN); - pw.print("(name=\""); - pw.print(fk.columnPair().baseColumn().getName()); - pw.print("\")"); - } else { - if (fk.columnPairsSize() > 1) { - pw.printAnnotation(JPA.JOIN_COLUMNS); - pw.print("({"); - pw.println(); - pw.indent(); - } - this.printJoinColumnAnnotationsOn(fk, pw); - if (fk.columnPairsSize() > 1) { - pw.undent(); + ForeignKey foreignKey = relation.getForeignKey(); + if (foreignKey.referencesSingleColumnPrimaryKey()) { + // if the FK references a single-column PK, 'referencedColumnName' is not required + String joinColumnName = this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(attributeName, foreignKey); + if (joinColumnName == null) { + // no JoinColumn annotation needed: the default 'name' and 'referencedColumnName' work + } else { + // there is only a single join column here (just not the default name) + this.printJoinColumnAnnotationOn(joinColumnName, null, pw); pw.println(); - pw.print("})"); } + } else { + this.printManyToOneJoinColumnsAnnotationOn(foreignKey, pw); + } + } + + private void printManyToOneJoinColumnsAnnotationOn(ForeignKey foreignKey, EntitySourceWriter pw) { + if (foreignKey.columnPairsSize() > 1) { + pw.printAnnotation(JPA.JOIN_COLUMNS); + pw.print("({"); //$NON-NLS-1$ + pw.println(); + pw.indent(); + } + this.printJoinColumnAnnotationsOn(foreignKey, pw); + if (foreignKey.columnPairsSize() > 1) { + pw.undent(); + pw.println(); + pw.print("})"); //$NON-NLS-1$ } pw.println(); } @@ -405,29 +371,35 @@ public class EntityGenerator { } private void printJoinColumnAnnotationOn(ForeignKey.ColumnPair columnPair, EntitySourceWriter pw) { - this.printJoinColumnAnnotationOn(columnPair.baseColumn().getName(), columnPair.referencedColumn().getName(), pw); + this.printJoinColumnAnnotationOn( + this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(columnPair.getBaseColumn()), + this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(columnPair.getReferencedColumn()), + pw + ); } /** - * assume that at least one of the two names is not null + * 'baseColumnName' cannot be null; + * 'referencedColumnName' is null when the default is applicable (i.e. the + * referenced column is the single-column primary key column of the + * referenced table) */ private void printJoinColumnAnnotationOn(String baseColumnName, String referencedColumnName, EntitySourceWriter pw) { pw.printAnnotation(JPA.JOIN_COLUMN); - pw.print('('); - if (baseColumnName != null) { - pw.print("name=\""); - pw.print(baseColumnName); - } + pw.print("(name="); //$NON-NLS-1$ + pw.printStringLiteral(baseColumnName); + if (referencedColumnName != null) { - if (baseColumnName != null) { - pw.print("\", "); - } - pw.print("referencedColumnName=\""); - pw.print(referencedColumnName); + pw.print(", referencedColumnName="); //$NON-NLS-1$ + pw.printStringLiteral(referencedColumnName); } - pw.print("\")"); + + pw.print(')'); } + + // ********** one-to-many fields ********** + private void printEntityOneToManyFieldsOn(EntitySourceWriter pw) { for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) { this.printEntityOneToManyFieldOn(stream.next(), pw); @@ -435,30 +407,24 @@ public class EntityGenerator { } private void printEntityOneToManyFieldOn(OneToManyRelation relation, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(relation); + String fieldName = this.genTable.getAttributeNameFor(relation); if (this.config.fieldAccessType()) { - this.printOneToManyAnnotationOn(fieldName, relation, pw); - } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(this.config.getCollectionTypeName()); - pw.print('<'); - pw.printTypeDeclaration(this.fullyQualify(relation.referencedEntityName())); - pw.print('>'); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printOneToManyAnnotationOn(relation, pw); + } + this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getReferencedEntityName()), pw); } - private void printOneToManyAnnotationOn(String fieldName, OneToManyRelation relation, EntitySourceWriter pw) { + private void printOneToManyAnnotationOn(OneToManyRelation relation, EntitySourceWriter pw) { pw.printAnnotation(JPA.ONE_TO_MANY); - pw.print("(mappedBy=\""); - pw.print(relation.mappedBy()); - pw.print("\")"); + pw.print("(mappedBy=\""); //$NON-NLS-1$ + pw.print(relation.getMappedBy()); + pw.print("\")"); //$NON-NLS-1$ pw.println(); } + + // ********** owned many-to-many fields ********** + private void printEntityOwnedManyToManyFieldsOn(EntitySourceWriter pw) { for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) { this.printEntityOwnedManyToManyFieldOn(stream.next(), pw); @@ -466,108 +432,102 @@ public class EntityGenerator { } private void printEntityOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(relation); + String fieldName = this.genTable.getAttributeNameFor(relation); if (this.config.fieldAccessType()) { this.printOwnedManyToManyAnnotationOn(fieldName, relation, pw); } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(this.config.getCollectionTypeName()); - pw.print('<'); - pw.printTypeDeclaration(this.fullyQualify(relation.nonOwningEntityName())); - pw.print('>'); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getNonOwningEntityName()), pw); } /** - * I guess you could build a state machine for all this crap, - * but that seems like overkill... + * only print the JoinTable annotation if one or more of the + * [generated] elements is not defaulted: + * name + * joinColumns + * inverseJoinColumns + * thus the need for the 'printJoinTableAnnotation' flag */ - private void printOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) { + private void printOwnedManyToManyAnnotationOn(String attributeName, ManyToManyRelation relation, EntitySourceWriter pw) { pw.printAnnotation(JPA.MANY_TO_MANY); pw.println(); - boolean first = true; - boolean comma = false; - if ( ! relation.joinTableNameIsDefault()) { - if (first) { - first = false; - pw.printAnnotation(JPA.JOIN_TABLE); - pw.print('('); - } - pw.print("name=\""); - pw.print(relation.getJoinTable().name()); - pw.print('\"'); - comma = true; - } - if ( ! relation.joinColumnsIsDefaultFor(fieldName)) { - if (first) { - first = false; - pw.printAnnotation(JPA.JOIN_TABLE); - pw.print('('); - } else if (comma) { - pw.print(','); - } + BooleanHolder printJoinTableAnnotation = new BooleanHolder(true); + + if ( ! relation.joinTableNameIsDefault()) { // db-only test - no need to delegate to platform? + printJoinTableAnnotation.setFalse(); + pw.printAnnotation(JPA.JOIN_TABLE); + pw.print("(name="); //$NON-NLS-1$ + pw.printStringLiteral(this.config.getDatabaseAnnotationNameBuilder().buildJoinTableAnnotationName(relation.getJoinGenTable().getTable())); + } + + this.printJoinTableJoinColumnAnnotationsOn( + "joinColumns", //$NON-NLS-1$ + attributeName, + relation.getOwningForeignKey(), + printJoinTableAnnotation, + pw + ); + + this.printJoinTableJoinColumnAnnotationsOn( + "inverseJoinColumns", //$NON-NLS-1$ + relation.getNonOwningGenTable().getAttributeNameFor(relation), + relation.getNonOwningForeignKey(), + printJoinTableAnnotation, + pw + ); + + if (printJoinTableAnnotation.isFalse()) { + pw.print(')'); pw.println(); - pw.indent(); - this.printJoinTableJoinColumnsOn("joinColumns", fieldName, relation.getOwningForeignKey(), pw); - pw.undent(); - comma = true; } - String inverseFieldName = relation.getNonOwningTable().fieldNameFor(relation); - if ( ! relation.inverseJoinColumnsIsDefaultFor(inverseFieldName)) { - if (first) { - first = false; + } + + /** + * 'elementName' is either "joinColumns" or "inverseJoinColumns" + */ + private void printJoinTableJoinColumnAnnotationsOn(String elementName, String attributeName, ForeignKey foreignKey, BooleanHolder printJoinTableAnnotation, EntitySourceWriter pw) { + // we have to pre-calculate whether either 'name' and/or 'referencedColumnName' + // is required because they are wrapped by the JoinTable annotation and we + // need to print the JoinTable annotation first (if it hasn't already been printed) + boolean printRef = ! foreignKey.referencesSingleColumnPrimaryKey(); + // if 'referencedColumnName' is required, 'name' is also required (i.e. it cannot be defaulted); + // but we will calculate it later [1], since there could be multiple join columns + String joinColumnName = (printRef) ? + null // 'joinColumnName' is not used + : + this.config.getDatabaseAnnotationNameBuilder().buildJoinColumnAnnotationName(attributeName, foreignKey); + boolean printBase = (printRef || (joinColumnName != null)); + if (printBase || printRef) { + if (printJoinTableAnnotation.isTrue()) { + printJoinTableAnnotation.setFalse(); pw.printAnnotation(JPA.JOIN_TABLE); pw.print('('); - } else if (comma) { + } else { pw.print(','); } pw.println(); pw.indent(); - this.printJoinTableJoinColumnsOn("inverseJoinColumns", inverseFieldName, relation.getNonOwningForeignKey(), pw); - pw.undent(); - comma = true; - } - if ( ! first) { - pw.print(')'); - } - pw.println(); - } - - private void printJoinTableJoinColumnsOn(String elementName, String fieldName, ForeignKey foreignKey, EntitySourceWriter pw) { - if (foreignKey.columnPairsSize() != 1) { - this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); - } else if (foreignKey.getReferencedTable().primaryKeyColumnsSize() != 1) { - // if the referenced table has a composite primary key, neither of the columns can be a default - // since both of the defaults require a single-column primary key - this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); - } else { - ForeignKey.ColumnPair columnPair = foreignKey.columnPair(); - Column pkColumn = foreignKey.getReferencedTable().primaryKeyColumn(); - if (columnPair.baseColumn().matchesJavaFieldName(fieldName + "_" + pkColumn.getName())) { - if (columnPair.referencedColumn() == pkColumn) { - // we shouldn't get here... - } else { - pw.print(elementName); - pw.print('='); - this.printJoinColumnAnnotationOn(null, columnPair.referencedColumn().getName(), pw); - } - } else { - if (columnPair.referencedColumn() == pkColumn) { - pw.print(elementName); - pw.print('='); - this.printJoinColumnAnnotationOn(columnPair.baseColumn().getName(), null, pw); + if (printRef) { + // if 'printRef' is true, 'joinColumnName' will always be "IGNORED" (so we ignore it) + this.printJoinTableJoinColumnAnnotationsOn(elementName, foreignKey, pw); // [1] } else { - this.printJoinTableJoinColumnsOn(elementName, foreignKey, pw); + // if the FK references a single-column PK, 'referencedColumnName' is not required + if (printBase) { + // there is only a single join column here (just not the default name) + pw.print(elementName); + pw.print('='); + this.printJoinColumnAnnotationOn(joinColumnName, null, pw); + } else { + // no JoinColumn annotation needed: the default 'name' and 'referencedColumnName' work + } } - } + pw.undent(); } } - private void printJoinTableJoinColumnsOn(String elementName, ForeignKey foreignKey, EntitySourceWriter pw) { + /** + * 'elementName' is either "joinColumns" or "inverseJoinColumns" + */ + private void printJoinTableJoinColumnAnnotationsOn(String elementName, ForeignKey foreignKey, EntitySourceWriter pw) { pw.print(elementName); pw.print('='); if (foreignKey.columnPairsSize() > 1) { @@ -584,6 +544,9 @@ public class EntityGenerator { } } + + // ********** non-owned many-to-many fields ********** + private void printEntityNonOwnedManyToManyFieldsOn(EntitySourceWriter pw) { for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) { this.printEntityNonOwnedManyToManyFieldOn(stream.next(), pw); @@ -591,38 +554,27 @@ public class EntityGenerator { } private void printEntityNonOwnedManyToManyFieldOn(ManyToManyRelation relation, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(relation); + String fieldName = this.genTable.getAttributeNameFor(relation); if (this.config.fieldAccessType()) { - this.printNonOwnedManyToManyAnnotationOn(fieldName, relation, pw); - } - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(this.config.getCollectionTypeName()); - pw.print('<'); - pw.printTypeDeclaration(this.fullyQualify(relation.owningEntityName())); - pw.print('>'); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); - pw.println(); + this.printNonOwnedManyToManyAnnotationOn(relation, pw); + } + this.printCollectionFieldOn(fieldName, this.fullyQualify(relation.getOwningEntityName()), pw); } - private void printNonOwnedManyToManyAnnotationOn(String fieldName, ManyToManyRelation relation, EntitySourceWriter pw) { + private void printNonOwnedManyToManyAnnotationOn(ManyToManyRelation relation, EntitySourceWriter pw) { pw.printAnnotation(JPA.MANY_TO_MANY); - pw.print("(mappedBy=\""); + pw.print("(mappedBy=\""); //$NON-NLS-1$ pw.print(relation.getMappedBy()); - pw.print("\")"); + pw.print("\")"); //$NON-NLS-1$ pw.println(); } - private String fullyQualify(String shortClassName) { - String pkg = this.packageName(); - return (pkg.length() == 0) ? shortClassName : pkg + '.' + shortClassName; - } - private void printSerialVersionUID(EntitySourceWriter pw) { + // ********** misc ********** + + private void printSerialVersionUIDFieldOn(EntitySourceWriter pw) { if (this.config.generateSerialVersionUID()) { - pw.print("private static final long serialVersionUID = 1L;"); + pw.print("private static final long serialVersionUID = 1L;"); //$NON-NLS-1$ pw.println(); } } @@ -631,10 +583,10 @@ public class EntityGenerator { if (this.config.generateDefaultConstructor()) { pw.printVisibility(visibility); pw.print(ctorName); - pw.print("() {"); + pw.print("() {"); //$NON-NLS-1$ pw.println(); pw.indent(); - pw.println("super();"); + pw.println("super();"); //$NON-NLS-1$ pw.undent(); pw.print('}'); pw.println(); @@ -642,170 +594,163 @@ public class EntityGenerator { } } - private void printEntityPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { - if (this.pkClassIsGenerated() && this.config.generateEmbeddedIdForCompoundPK()) { - this.printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(pw); + + // ********** primary key properties ********** + + private void printEntityPrimaryKeyPropertiesOn(EntitySourceWriter pw) { + if (this.primaryKeyClassIsRequired() && this.config.generateEmbeddedIdForCompoundPK()) { + this.printEntityEmbeddedIdPrimaryKeyPropertyOn(pw); } else { - this.printEntityReadOnlyPrimaryKeyGettersAndSettersOn(pw); - this.printEntityWritablePrimaryKeyGettersAndSettersOn(pw); + this.printEntityReadOnlyPrimaryKeyPropertiesOn(pw); + this.printEntityWritablePrimaryKeyPropertiesOn(pw); } } - private void printEntityEmbeddedIdPrimaryKeyGetterAndSetterOn(EntitySourceWriter pw) { + private void printEntityEmbeddedIdPrimaryKeyPropertyOn(EntitySourceWriter pw) { if (this.config.propertyAccessType()) { pw.printAnnotation(JPA.EMBEDDED_ID); pw.println(); } - pw.printGetterAndSetter(this.genTable.fieldNameForEmbeddedId(), this.pkClassName, this.config.methodVisibility()); + this.printPropertyOn(this.genTable.getAttributeNameForEmbeddedId(), this.pkClassName, pw); + } + + private void printEntityReadOnlyPrimaryKeyPropertiesOn(EntitySourceWriter pw) { + this.printPrimaryKeyPropertiesOn(pw, true, true); // true=read-only; true=print ID annotation on getters } - private void printEntityReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { - this.printReadOnlyPrimaryKeyGettersAndSettersOn(pw, true); // true=print ID annotation on fields + private void printEntityWritablePrimaryKeyPropertiesOn(EntitySourceWriter pw) { + this.printPrimaryKeyPropertiesOn(pw, false, true); // false=writable; true=print ID annotation on getters } - private void printReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw, boolean printIdAnnotation) { - for (Iterator<Column> stream = this.genTable.readOnlyPrimaryKeyColumns(); stream.hasNext(); ) { - this.printReadOnlyPrimaryKeyGetterAndSetterOn(stream.next(), pw, printIdAnnotation); + private void printPrimaryKeyPropertiesOn(EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) { + for (Iterator<Column> stream = this.primaryKeyColumns(readOnly); stream.hasNext(); ) { + this.printPrimaryKeyPropertyOn(stream.next(), pw, readOnly, printIdAnnotation); } } - // TODO if the property's type is java.util.Date, it needs @Temporal(DATE) + // TODO if the property's type is java.util/sql.Date, it needs @Temporal(DATE) // TODO if the primary key is auto-generated, the property must be an integral type - private void printReadOnlyPrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) { - String propertyName = this.genTable.fieldNameFor(column); + private void printPrimaryKeyPropertyOn(Column column, EntitySourceWriter pw, boolean readOnly, boolean printIdAnnotation) { + String propertyName = this.genTable.getAttributeNameFor(column); if (this.config.propertyAccessType()) { if (printIdAnnotation) { pw.printAnnotation(JPA.ID); pw.println(); } - if (column.matchesJavaFieldName(propertyName)) { - this.printReadOnlyColumnAnnotationOn(pw); // no Column name needed + String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(propertyName, column); + if (readOnly) { + this.printReadOnlyColumnAnnotationOn(columnName, pw); } else { - this.printReadOnlyColumnAnnotationOn(column.getName(), pw); + this.printColumnAnnotationOn(columnName, pw); } } - - pw.printGetterAndSetter(propertyName, column.getPrimaryKeyJavaTypeDeclaration(), this.config.methodVisibility()); - } - - private void printEntityWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { - this.printWritablePrimaryKeyGettersAndSettersOn(pw, true); // true=print ID annotation on fields + this.printPropertyOn(propertyName, column.getPrimaryKeyJavaTypeDeclaration(), pw); } - private void printWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw, boolean printIdAnnotation) { - for (Iterator<Column> stream = this.genTable.writablePrimaryKeyColumns(); stream.hasNext(); ) { - this.printWritablePrimaryKeyGetterAndSetterOn(stream.next(), pw, printIdAnnotation); - } - } - - // TODO if the property's type is java.util.Date, it needs @Temporal(DATE) - // TODO if the primary key is auto-generated, the property must be an integral type - private void printWritablePrimaryKeyGetterAndSetterOn(Column column, EntitySourceWriter pw, boolean printIdAnnotation) { - String propertyName = this.genTable.fieldNameFor(column); - if (this.config.propertyAccessType()) { - if (printIdAnnotation) { - pw.printAnnotation(JPA.ID); - pw.println(); - } - if ( ! column.matchesJavaFieldName(propertyName)) { - this.printColumnAnnotationOn(column.getName(), pw); - } - } - pw.printGetterAndSetter(propertyName, column.getPrimaryKeyJavaTypeDeclaration(), this.config.methodVisibility()); - } + // ********** basic properties ********** - private void printEntityNonPrimaryKeyBasicGettersAndSettersOn(EntitySourceWriter pw) { + private void printEntityNonPrimaryKeyBasicPropertiesOn(EntitySourceWriter pw) { for (Iterator<Column> stream = this.genTable.nonPrimaryKeyBasicColumns(); stream.hasNext(); ) { - this.printEntityNonPrimaryKeyBasicGetterAndSetterOn(stream.next(), pw); + this.printEntityNonPrimaryKeyBasicPropertyOn(stream.next(), pw); } } - private void printEntityNonPrimaryKeyBasicGetterAndSetterOn(Column column, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(column); + private void printEntityNonPrimaryKeyBasicPropertyOn(Column column, EntitySourceWriter pw) { + String propertyName = this.genTable.getAttributeNameFor(column); if (this.config.propertyAccessType()) { - if ( ! column.matchesJavaFieldName(propertyName)) { - this.printColumnAnnotationOn(column.getName(), pw); - } + String columnName = this.config.getDatabaseAnnotationNameBuilder().buildColumnAnnotationName(propertyName, column); + this.printColumnAnnotationOn(columnName, pw); } - - pw.printGetterAndSetter(propertyName, column.getJavaTypeDeclaration(), this.config.methodVisibility()); + this.printPropertyOn(propertyName, column.getJavaTypeDeclaration(), pw); } - private void printEntityManyToOneGettersAndSettersOn(EntitySourceWriter pw) { + + // ********** many-to-one properties ********** + + private void printEntityManyToOnePropertiesOn(EntitySourceWriter pw) { for (Iterator<ManyToOneRelation> stream = this.genTable.manyToOneRelations(); stream.hasNext(); ) { - this.printEntityManyToOneGetterAndSetterOn(stream.next(), pw); + this.printEntityManyToOnePropertyOn(stream.next(), pw); } } - private void printEntityManyToOneGetterAndSetterOn(ManyToOneRelation relation, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(relation); + private void printEntityManyToOnePropertyOn(ManyToOneRelation relation, EntitySourceWriter pw) { + String propertyName = this.genTable.getAttributeNameFor(relation); if (this.config.propertyAccessType()) { this.printManyToOneAnnotationOn(propertyName, relation, pw); } - - String typeDeclaration = this.fullyQualify(relation.referencedEntityName()); - pw.printGetterAndSetter(propertyName, typeDeclaration, this.config.methodVisibility()); + String typeDeclaration = this.fullyQualify(relation.getReferencedEntityName()); + this.printPropertyOn(propertyName, typeDeclaration, pw); } - private void printEntityOneToManyGettersAndSettersOn(EntitySourceWriter pw) { + + // ********** one-to-many properties ********** + + private void printEntityOneToManyPropertiesOn(EntitySourceWriter pw) { for (Iterator<OneToManyRelation> stream = this.genTable.oneToManyRelations(); stream.hasNext(); ) { - this.printEntityOneToManyGetterAndSetterOn(stream.next(), pw); + this.printEntityOneToManyPropertyOn(stream.next(), pw); } } - private void printEntityOneToManyGetterAndSetterOn(OneToManyRelation relation, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(relation); + private void printEntityOneToManyPropertyOn(OneToManyRelation relation, EntitySourceWriter pw) { + String propertyName = this.genTable.getAttributeNameFor(relation); if (this.config.propertyAccessType()) { - this.printOneToManyAnnotationOn(propertyName, relation, pw); + this.printOneToManyAnnotationOn(relation, pw); } - - String elementTypeDeclaration = this.fullyQualify(relation.referencedEntityName()); - pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); + String elementTypeDeclaration = this.fullyQualify(relation.getReferencedEntityName()); + this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw); } - private void printEntityOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) { + + // ********** owned many-to-many properties ********** + + private void printEntityOwnedManyToManyPropertiesOn(EntitySourceWriter pw) { for (Iterator<ManyToManyRelation> stream = this.genTable.ownedManyToManyRelations(); stream.hasNext(); ) { - this.printEntityOwnedManyToManyGetterAndSetterOn(stream.next(), pw); + this.printEntityOwnedManyToManyPropertyOn(stream.next(), pw); } } - private void printEntityOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(relation); + private void printEntityOwnedManyToManyPropertyOn(ManyToManyRelation relation, EntitySourceWriter pw) { + String propertyName = this.genTable.getAttributeNameFor(relation); if (this.config.propertyAccessType()) { this.printOwnedManyToManyAnnotationOn(propertyName, relation, pw); } - - String elementTypeDeclaration = this.fullyQualify(relation.nonOwningEntityName()); - pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); + String elementTypeDeclaration = this.fullyQualify(relation.getNonOwningEntityName()); + this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw); } - private void printEntityNonOwnedManyToManyGettersAndSettersOn(EntitySourceWriter pw) { + + // ********** non-owned many-to-many properties ********** + + private void printEntityNonOwnedManyToManyPropertiesOn(EntitySourceWriter pw) { for (Iterator<ManyToManyRelation> stream = this.genTable.nonOwnedManyToManyRelations(); stream.hasNext(); ) { - this.printEntityNonOwnedManyToManyGetterAndSetterOn(stream.next(), pw); + this.printEntityNonOwnedManyToManyPropertyOn(stream.next(), pw); } } - private void printEntityNonOwnedManyToManyGetterAndSetterOn(ManyToManyRelation relation, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(relation); + private void printEntityNonOwnedManyToManyPropertyOn(ManyToManyRelation relation, EntitySourceWriter pw) { + String propertyName = this.genTable.getAttributeNameFor(relation); if (this.config.propertyAccessType()) { - this.printNonOwnedManyToManyAnnotationOn(propertyName, relation, pw); + this.printNonOwnedManyToManyAnnotationOn(relation, pw); } - - String elementTypeDeclaration = this.fullyQualify(relation.owningEntityName()); - pw.printCollectionGetterAndSetter(propertyName, this.config.getCollectionTypeName(), elementTypeDeclaration, this.config.methodVisibility()); + String elementTypeDeclaration = this.fullyQualify(relation.getOwningEntityName()); + this.printCollectionPropertyOn(propertyName, elementTypeDeclaration, pw); } + + // ********** compound primary key class ********** + private void printPrimaryKeyClassOn(EntitySourceWriter pw) { + pw.println(); if (this.config.generateEmbeddedIdForCompoundPK()) { pw.printAnnotation(JPA.EMBEDDABLE); pw.println(); } - pw.print("public class "); - pw.printTypeDeclaration(this.pkClassName); - pw.print(" implements "); + pw.print("public static class "); //$NON-NLS-1$ + pw.print(this.config.getPrimaryKeyMemberClassName()); + pw.print(" implements "); //$NON-NLS-1$ pw.printTypeDeclaration(Serializable.class.getName()); - pw.print(" {"); + pw.print(" {"); //$NON-NLS-1$ pw.println(); pw.indent(); @@ -815,106 +760,109 @@ public class EntityGenerator { } else { this.printIdFieldsOn(pw); } - this.printSerialVersionUID(pw); + this.printSerialVersionUIDFieldOn(pw); pw.println(); - this.printZeroArgumentConstructorOn(this.pkName(), "public", pw); + this.printZeroArgumentConstructorOn(this.config.getPrimaryKeyMemberClassName(), "public", pw); //$NON-NLS-1$ if (this.config.propertyAccessType() || this.config.generateGettersAndSetters()) { if (this.config.generateEmbeddedIdForCompoundPK()) { - this.printEmbeddableReadOnlyPrimaryKeyGettersAndSettersOn(pw); - this.printEmbeddableWritablePrimaryKeyGettersAndSettersOn(pw); + this.printEmbeddableReadOnlyPrimaryKeyPropertiesOn(pw); + this.printEmbeddableWritablePrimaryKeyPropertiesOn(pw); } else { - this.printIdGettersAndSettersOn(pw); + this.printIdPropertiesOn(pw); } } - this.printPrimaryKeyEqualsMethodOn(this.pkName(), this.table().primaryKeyColumns(), pw); - this.printPrimaryKeyHashCodeMethodOn(this.table().primaryKeyColumns(), pw); + this.printPrimaryKeyEqualsMethodOn(this.config.getPrimaryKeyMemberClassName(), this.getTable().primaryKeyColumns(), pw); + this.printPrimaryKeyHashCodeMethodOn(this.getTable().primaryKeyColumns(), pw); pw.undent(); pw.print('}'); pw.println(); + pw.println(); } + + // ********** compound primary key class fields ********** + private void printEmbeddableReadOnlyPrimaryKeyFieldsOn(EntitySourceWriter pw) { - this.printReadOnlyPrimaryKeyFieldsOn(pw, false); // false=do not print ID annotation on fields + this.printPrimaryKeyFieldsOn(pw, true, false); // true=read-only; false=do not print ID annotation on fields } private void printEmbeddableWritablePrimaryKeyFieldsOn(EntitySourceWriter pw) { - this.printWritablePrimaryKeyFieldsOn(pw, false); // false=do not print ID annotation on fields + this.printPrimaryKeyFieldsOn(pw, false, false); // false=writable; false=do not print ID annotation on fields } private void printIdFieldsOn(EntitySourceWriter pw) { - for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) { + for (Iterator<Column> stream = this.getTable().primaryKeyColumns(); stream.hasNext(); ) { this.printIdFieldOn(stream.next(), pw); } } private void printIdFieldOn(Column column, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(column); - pw.printVisibility(this.config.fieldVisibility()); - pw.printTypeDeclaration(column.getPrimaryKeyJavaTypeDeclaration()); - pw.print(' '); - pw.print(fieldName); - pw.print(';'); - pw.println(); + this.printFieldOn(this.genTable.getAttributeNameFor(column), column.getPrimaryKeyJavaTypeDeclaration(), pw); } - private void printEmbeddableReadOnlyPrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { - this.printReadOnlyPrimaryKeyGettersAndSettersOn(pw, false); // false=do not print ID annotation on fields + + // ********** compound primary key class properties ********** + + private void printEmbeddableReadOnlyPrimaryKeyPropertiesOn(EntitySourceWriter pw) { + this.printPrimaryKeyPropertiesOn(pw, true, false); // true=read-only; false=do not print ID annotation on getters } - private void printEmbeddableWritablePrimaryKeyGettersAndSettersOn(EntitySourceWriter pw) { - this.printWritablePrimaryKeyGettersAndSettersOn(pw, false); // false=do not print ID annotation on fields + private void printEmbeddableWritablePrimaryKeyPropertiesOn(EntitySourceWriter pw) { + this.printPrimaryKeyPropertiesOn(pw, false, false); // false=writable; false=do not print ID annotation on getters } - private void printIdGettersAndSettersOn(EntitySourceWriter pw) { - for (Iterator<Column> stream = this.table().primaryKeyColumns(); stream.hasNext(); ) { - this.printIdGetterAndSetterOn(stream.next(), pw); + private void printIdPropertiesOn(EntitySourceWriter pw) { + for (Iterator<Column> stream = this.getTable().primaryKeyColumns(); stream.hasNext(); ) { + this.printIdPropertyOn(stream.next(), pw); } } - private void printIdGetterAndSetterOn(Column column, EntitySourceWriter pw) { - String propertyName = this.genTable.fieldNameFor(column); - pw.printGetterAndSetter(propertyName, column.getPrimaryKeyJavaTypeDeclaration(), this.config.methodVisibility()); + private void printIdPropertyOn(Column column, EntitySourceWriter pw) { + this.printPropertyOn(this.genTable.getAttributeNameFor(column), column.getPrimaryKeyJavaTypeDeclaration(), pw); } + + // ********** compound primary key class equals ********** + private void printPrimaryKeyEqualsMethodOn(String className, Iterator<Column> columns, EntitySourceWriter pw) { - pw.printAnnotation("java.lang.Override"); + pw.printAnnotation("java.lang.Override"); //$NON-NLS-1$ pw.println(); - pw.println("public boolean equals(Object o) {"); + pw.println("public boolean equals(Object o) {"); //$NON-NLS-1$ pw.indent(); - pw.println("if (o == this) {"); + pw.println("if (o == this) {"); //$NON-NLS-1$ pw.indent(); - pw.println("return true;"); + pw.println("return true;"); //$NON-NLS-1$ pw.undent(); pw.print('}'); pw.println(); - pw.print("if ( ! (o instanceof "); + pw.print("if ( ! (o instanceof "); //$NON-NLS-1$ pw.print(className); - pw.print(")) {"); + pw.print(")) {"); //$NON-NLS-1$ pw.println(); pw.indent(); - pw.println("return false;"); + pw.println("return false;"); //$NON-NLS-1$ pw.undent(); pw.print('}'); pw.println(); pw.print(className); - pw.print(" other = ("); + pw.print(" other = ("); //$NON-NLS-1$ pw.print(className); - pw.print(") o;"); + pw.print(") o;"); //$NON-NLS-1$ pw.println(); - pw.print("return "); + pw.print("return "); //$NON-NLS-1$ pw.indent(); while (columns.hasNext()) { this.printPrimaryKeyEqualsClauseOn(columns.next(), pw); if (columns.hasNext()) { pw.println(); - pw.print("&& "); + pw.print("&& "); //$NON-NLS-1$ } } pw.print(';'); @@ -927,7 +875,7 @@ public class EntityGenerator { } private void printPrimaryKeyEqualsClauseOn(Column column, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(column); + String fieldName = this.genTable.getAttributeNameFor(column); JavaType javaType = column.getPrimaryKeyJavaType(); if (javaType.isPrimitive()) { this.printPrimitiveEqualsClauseOn(fieldName, pw); @@ -937,36 +885,39 @@ public class EntityGenerator { } private void printPrimitiveEqualsClauseOn(String fieldName, EntitySourceWriter pw) { - pw.print("(this."); + pw.print("(this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(" == other."); + pw.print(" == other."); //$NON-NLS-1$ pw.print(fieldName); pw.print(')'); } private void printReferenceEqualsClauseOn(String fieldName, EntitySourceWriter pw) { - pw.print("this."); + pw.print("this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(".equals(other."); + pw.print(".equals(other."); //$NON-NLS-1$ pw.print(fieldName); pw.print(')'); } + + // ********** compound primary key class hash code ********** + private void printPrimaryKeyHashCodeMethodOn(Iterator<Column> columns, EntitySourceWriter pw) { - pw.printAnnotation("java.lang.Override"); + pw.printAnnotation("java.lang.Override"); //$NON-NLS-1$ pw.println(); - pw.println("public int hashCode() {"); + pw.println("public int hashCode() {"); //$NON-NLS-1$ pw.indent(); - pw.println("final int prime = 31;"); - pw.println("int hash = 17;"); + pw.println("final int prime = 31;"); //$NON-NLS-1$ + pw.println("int hash = 17;"); //$NON-NLS-1$ while (columns.hasNext()) { - pw.print("hash = hash * prime + "); + pw.print("hash = hash * prime + "); //$NON-NLS-1$ this.printPrimaryKeyHashCodeClauseOn(columns.next(), pw); pw.print(';'); pw.println(); } - pw.println("return hash;"); + pw.println("return hash;"); //$NON-NLS-1$ pw.undent(); pw.print('}'); pw.println(); @@ -974,7 +925,7 @@ public class EntityGenerator { } private void printPrimaryKeyHashCodeClauseOn(Column column, EntitySourceWriter pw) { - String fieldName = this.genTable.fieldNameFor(column); + String fieldName = this.genTable.getAttributeNameFor(column); JavaType javaType = column.getPrimaryKeyJavaType(); if (javaType.isPrimitive()) { this.printPrimitiveHashCodeClauseOn(javaType.getElementTypeName(), fieldName, pw); @@ -984,59 +935,64 @@ public class EntityGenerator { } private void printPrimitiveHashCodeClauseOn(String primitiveName, String fieldName, EntitySourceWriter pw) { - if (primitiveName.equals("int")) { + if (primitiveName.equals("int")) { //$NON-NLS-1$ // this.value - pw.print("this."); + pw.print("this."); //$NON-NLS-1$ pw.print(fieldName); - } else if (primitiveName.equals("short") || primitiveName.equals("byte") || primitiveName.equals("char")) { // explicit cast - // ((int) this.value) - pw.print("((int) this."); + } else if (primitiveName.equals("short") //$NON-NLS-1$ + || primitiveName.equals("byte") //$NON-NLS-1$ + || primitiveName.equals("char")) { //$NON-NLS-1$ + // ((int) this.value) - explicit cast + pw.print("((int) this."); //$NON-NLS-1$ pw.print(fieldName); pw.print(')'); - } else if (primitiveName.equals("long")) { // cribbed from Long#hashCode() + } else if (primitiveName.equals("long")) { // cribbed from Long#hashCode() //$NON-NLS-1$ // ((int) (this.value ^ (this.value >>> 32))) - pw.print("((int) (this."); + pw.print("((int) (this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(" ^ (this."); + pw.print(" ^ (this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(" >>> 32)))"); - } else if (primitiveName.equals("float")) { // cribbed from Float#hashCode() + pw.print(" >>> 32)))"); //$NON-NLS-1$ + } else if (primitiveName.equals("float")) { // cribbed from Float#hashCode() //$NON-NLS-1$ // java.lang.Float.floatToIntBits(this.value) - pw.printTypeDeclaration("java.lang.Float"); - pw.print(".floatToIntBits(this."); + pw.printTypeDeclaration("java.lang.Float"); //$NON-NLS-1$ + pw.print(".floatToIntBits(this."); //$NON-NLS-1$ pw.print(fieldName); pw.print(')'); - } else if (primitiveName.equals("double")) { // cribbed from Double#hashCode() + } else if (primitiveName.equals("double")) { // cribbed from Double#hashCode() //$NON-NLS-1$ // ((int) (java.lang.Double.doubleToLongBits(this.value) ^ (java.lang.Double.doubleToLongBits(this.value) >>> 32))) - pw.print("((int) ("); - pw.printTypeDeclaration("java.lang.Double"); - pw.print(".doubleToLongBits(this."); + pw.print("((int) ("); //$NON-NLS-1$ + pw.printTypeDeclaration("java.lang.Double"); //$NON-NLS-1$ + pw.print(".doubleToLongBits(this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(") ^ ("); - pw.printTypeDeclaration("java.lang.Double"); - pw.print(".doubleToLongBits(this."); + pw.print(") ^ ("); //$NON-NLS-1$ + pw.printTypeDeclaration("java.lang.Double"); //$NON-NLS-1$ + pw.print(".doubleToLongBits(this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(") >>> 32)))"); - } else if (primitiveName.equals("boolean")) { + pw.print(") >>> 32)))"); //$NON-NLS-1$ + } else if (primitiveName.equals("boolean")) { //$NON-NLS-1$ // (this.value ? 1 : 0) - pw.print("(this."); + pw.print("(this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(" ? 1 : 0)"); + pw.print(" ? 1 : 0)"); //$NON-NLS-1$ } else { throw new IllegalArgumentException(primitiveName); } } private void printReferenceHashCodeClauseOn(String fieldName, EntitySourceWriter pw) { - pw.print("this."); + pw.print("this."); //$NON-NLS-1$ pw.print(fieldName); - pw.print(".hashCode()"); + pw.print(".hashCode()"); //$NON-NLS-1$ } + + // ********** package and imports ********** + private void printPackageAndImportsOn(PrintWriter pw, BodySource bodySource) { - if (this.packageName().length() != 0) { - pw.print("package "); - pw.print(this.packageName()); + if (this.getPackageName().length() != 0) { + pw.print("package "); //$NON-NLS-1$ + pw.print(this.getPackageName()); pw.print(';'); pw.println(); pw.println(); @@ -1044,7 +1000,7 @@ public class EntityGenerator { for (Iterator<Map.Entry<String, String>> stream = bodySource.importEntries(); stream.hasNext(); ) { Map.Entry<String, String> entry = stream.next(); - pw.print("import "); + pw.print("import "); //$NON-NLS-1$ pw.print(entry.getValue()); // package pw.print('.'); pw.print(entry.getKey()); // short class name @@ -1055,30 +1011,88 @@ public class EntityGenerator { } + // ********** fields ********** + + /** + * visibility is set in the config + */ + private void printFieldOn(String fieldName, String typeDeclaration, EntitySourceWriter pw) { + pw.printField( + fieldName, + typeDeclaration, + this.config.getFieldVisibilityClause() + ); + } + + /** + * visibility and collection type are set in the config + */ + private void printCollectionFieldOn(String fieldName, String elementTypeDeclaration, EntitySourceWriter pw) { + pw.printParameterizedField( + fieldName, + this.config.getCollectionTypeName(), + elementTypeDeclaration, + this.config.getFieldVisibilityClause() + ); + } + + + // ********** properties ********** + + /** + * visibility is set in the config + */ + private void printPropertyOn(String propertyName, String typeDeclaration, EntitySourceWriter pw) { + pw.printGetterAndSetter( + propertyName, + typeDeclaration, + this.config.getMethodVisibilityClause() + ); + } + + /** + * visibility and collection type are set in the config + */ + private void printCollectionPropertyOn(String propertyName, String elementTypeDeclaration, EntitySourceWriter pw) { + pw.printCollectionGetterAndSetter( + propertyName, + this.config.getCollectionTypeName(), + elementTypeDeclaration, + this.config.getMethodVisibilityClause() + ); + } + + // ********** convenience methods ********** - private String packageName() { + private String getPackageName() { return this.packageFragment.getElementName(); } - private Table table() { + private Table getTable() { return this.genTable.getTable(); } - private String entityName() { + private String getEntityName() { return this.genTable.getEntityName(); } - private String pkName() { - return this.entityName() + "PK"; // hack + private boolean primaryKeyClassIsRequired() { + return this.getTable().primaryKeyColumnsSize() > 1; + } + + private String fullyQualify(String shortClassName) { + String pkg = this.getPackageName(); + return (pkg.length() == 0) ? shortClassName : pkg + '.' + shortClassName; } - private boolean pkClassIsGenerated() { - return this.table().primaryKeyColumnsSize() > 1; + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.genTable.getName() + " => " + this.entityClassName); //$NON-NLS-1$ } - // ********** writer ********** + // ********** source writer ********** private interface BodySource { @@ -1091,7 +1105,7 @@ public class EntityGenerator { /** * return the body source code */ - String source(); + String getSource(); /** * return the length of the body source code @@ -1116,6 +1130,15 @@ public class EntityGenerator { this.className = className; } + /** + * Convert the specified string to a String Literal and print it, + * adding the surrounding double-quotes and escaping characters + * as necessary. + */ + void printStringLiteral(String string) { + StringTools.convertToJavaStringLiteralOn(string, this); + } + void printVisibility(String visibilityModifier) { if (visibilityModifier.length() != 0) { this.print(visibilityModifier); @@ -1129,7 +1152,7 @@ public class EntityGenerator { } void printTypeDeclaration(String typeDeclaration) { - this.print(this.importedTypeDeclaration(typeDeclaration)); + this.print(this.buildImportedTypeDeclaration(typeDeclaration)); } /** @@ -1142,16 +1165,16 @@ public class EntityGenerator { * "java.util.Map.Entry" (not "java.util.Map$Entry") * "java.util.Map.Entry[][]" (not "[[Ljava.util.Map$Entry;") */ - private String importedTypeDeclaration(String typeDeclaration) { + private String buildImportedTypeDeclaration(String typeDeclaration) { if (this.typeDeclarationIsMemberClass(typeDeclaration)) { // no need for an import, just return the partially-qualified name - return this.memberClassTypeDeclaration(typeDeclaration); + return this.buildMemberClassTypeDeclaration(typeDeclaration); } int last = typeDeclaration.lastIndexOf('.'); - String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last); + String pkg = (last == -1) ? "" : typeDeclaration.substring(0, last); //$NON-NLS-1$ String shortTypeDeclaration = typeDeclaration.substring(last + 1); String shortElementTypeName = shortTypeDeclaration; - while (shortElementTypeName.endsWith("[]")) { + while (shortElementTypeName.endsWith("[]")) { //$NON-NLS-1$ shortElementTypeName = shortElementTypeName.substring(0, shortElementTypeName.length() - 2); } String prev = this.imports.get(shortElementTypeName); @@ -1182,7 +1205,7 @@ public class EntityGenerator { * e.g. "foo.bar.Employee.PK" will return "Employee.PK" * this prevents collisions with other imported classes (e.g. "joo.jar.PK") */ - private String memberClassTypeDeclaration(String typeDeclaration) { + private String buildMemberClassTypeDeclaration(String typeDeclaration) { int index = this.packageName.length(); if (index != 0) { index++; // bump past the '.' @@ -1190,21 +1213,6 @@ public class EntityGenerator { return typeDeclaration.substring(index); } - public Iterator<Map.Entry<String, String>> importEntries() { - return new FilteringIterator<Map.Entry<String, String>, Map.Entry<String, String>>(this.sortedImportEntries()) { - @Override - protected boolean accept(Map.Entry<String, String> next) { - String pkg = next.getValue(); - if (pkg.equals("") - || pkg.equals("java.lang") - || pkg.equals(EntitySourceWriter.this.packageName)) { - return false; - } - return true; - } - }; - } - private Iterator<Map.Entry<String, String>> sortedImportEntries() { TreeSet<Map.Entry<String, String>> sortedImports = new TreeSet<Map.Entry<String, String>>(this.buildImportEntriesComparator()); sortedImports.addAll(this.imports.entrySet()); @@ -1221,6 +1229,29 @@ public class EntityGenerator { }; } + void printField(String fieldName, String typeDeclaration, String visibility) { + this.printVisibility(visibility); + this.printTypeDeclaration(typeDeclaration); + this.print(' '); + this.print(fieldName); + this.print(';'); + this.println(); + this.println(); + } + + void printParameterizedField(String fieldName, String typeDeclaration, String parameterTypeDeclaration, String visibility) { + this.printVisibility(visibility); + this.printTypeDeclaration(typeDeclaration); + this.print('<'); + this.printTypeDeclaration(parameterTypeDeclaration); + this.print('>'); + this.print(' '); + this.print(fieldName); + this.print(';'); + this.println(); + this.println(); + } + void printGetterAndSetter(String propertyName, String typeDeclaration, String visibility) { this.printGetter(propertyName, typeDeclaration, visibility); this.println(); @@ -1235,13 +1266,13 @@ public class EntityGenerator { this.printVisibility(visibility); this.printTypeDeclaration(typeDeclaration); this.print(' '); - this.print(typeDeclaration.equals("boolean") ? "is" : "get"); + this.print(typeDeclaration.equals("boolean") ? "is" : "get"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ this.print(StringTools.capitalize(propertyName)); - this.print("() {"); + this.print("() {"); //$NON-NLS-1$ this.println(); this.indent(); - this.print("return this."); + this.print("return this."); //$NON-NLS-1$ this.print(propertyName); this.print(';'); this.println(); @@ -1252,19 +1283,19 @@ public class EntityGenerator { private void printSetter(String propertyName, String typeDeclaration, String visibility) { this.printVisibility(visibility); - this.print("void set"); + this.print("void set"); //$NON-NLS-1$ this.print(StringTools.capitalize(propertyName)); this.print('('); this.printTypeDeclaration(typeDeclaration); this.print(' '); this.print(propertyName); - this.print(") {"); + this.print(") {"); //$NON-NLS-1$ this.println(); this.indent(); - this.print("this."); + this.print("this."); //$NON-NLS-1$ this.print(propertyName); - this.print(" = "); + this.print(" = "); //$NON-NLS-1$ this.print(propertyName); this.print(';'); this.println(); @@ -1288,13 +1319,13 @@ public class EntityGenerator { this.printTypeDeclaration(collectionTypeDeclaration); this.print('<'); this.printTypeDeclaration(elementTypeDeclaration); - this.print("> get"); + this.print("> get"); //$NON-NLS-1$ this.print(StringTools.capitalize(propertyName)); - this.print("() {"); + this.print("() {"); //$NON-NLS-1$ this.println(); this.indent(); - this.print("return this."); + this.print("return this."); //$NON-NLS-1$ this.print(propertyName); this.print(';'); this.println(); @@ -1305,7 +1336,7 @@ public class EntityGenerator { private void printCollectionSetter(String propertyName, String collectionTypeDeclaration, String elementTypeDeclaration, String visibility) { this.printVisibility(visibility); - this.print("void set"); + this.print("void set"); //$NON-NLS-1$ this.print(StringTools.capitalize(propertyName)); this.print('('); this.printTypeDeclaration(collectionTypeDeclaration); @@ -1314,13 +1345,13 @@ public class EntityGenerator { this.print('>'); this.print(' '); this.print(propertyName); - this.print(") {"); + this.print(") {"); //$NON-NLS-1$ this.println(); this.indent(); - this.print("this."); + this.print("this."); //$NON-NLS-1$ this.print(propertyName); - this.print(" = "); + this.print(" = "); //$NON-NLS-1$ this.print(propertyName); this.print(';'); this.println(); @@ -1329,7 +1360,25 @@ public class EntityGenerator { this.print('}'); } - public String source() { + + // ********** BodySource implementation ********** + + public Iterator<Map.Entry<String, String>> importEntries() { + return new FilteringIterator<Map.Entry<String, String>, Map.Entry<String, String>>(this.sortedImportEntries()) { + @Override + protected boolean accept(Map.Entry<String, String> next) { + String pkg = next.getValue(); + if (pkg.equals("") //$NON-NLS-1$ + || pkg.equals("java.lang") //$NON-NLS-1$ + || pkg.equals(EntitySourceWriter.this.packageName)) { + return false; + } + return true; + } + }; + } + + public String getSource() { return this.out.toString(); } @@ -1343,17 +1392,35 @@ public class EntityGenerator { // ********** config ********** public static class Config { - private boolean convertToCamelCase = true; + private boolean convertToJavaStyleIdentifiers = true; + private boolean propertyAccessType = false; // as opposed to "field" + private String collectionTypeName = Set.class.getName(); + private String collectionAttributeNameSuffix = "_collection"; // e.g. "private Set<Foo> foo_collection" //$NON-NLS-1$ + private int fieldVisibility = Modifier.PRIVATE; private int methodVisibility = Modifier.PUBLIC; + private boolean generateGettersAndSetters = true; private boolean generateDefaultConstructor = true; + private boolean serializable = true; private boolean generateSerialVersionUID = true; + private boolean generateEmbeddedIdForCompoundPK = true; // as opposed to IdClass - private Map<Table, String> overrideEntityNames = new HashMap<Table, String>(); + private String embeddedIdAttributeName = "pk"; //$NON-NLS-1$ + private String primaryKeyMemberClassName = "PK"; //$NON-NLS-1$ + + /** + * key = table + * value = entity name + */ + private HashMap<Table, String> tables = new HashMap<Table, String>(); + + private DatabaseAnnotationNameBuilder databaseAnnotationNameBuilder = DatabaseAnnotationNameBuilder.Default.INSTANCE; + + private OverwriteConfirmer overwriteConfirmer = OverwriteConfirmer.Never.INSTANCE; public static final int PRIVATE = 0; public static final int PACKAGE = 1; @@ -1361,11 +1428,11 @@ public class EntityGenerator { public static final int PUBLIC = 3; - public boolean convertToCamelCase() { - return this.convertToCamelCase; + public boolean convertToJavaStyleIdentifiers() { + return this.convertToJavaStyleIdentifiers; } - public void setConvertToCamelCase(boolean convertToCamelCase) { - this.convertToCamelCase = convertToCamelCase; + public void setConvertToJavaStyleIdentifiers(boolean convertToJavaStyleIdentifiers) { + this.convertToJavaStyleIdentifiers = convertToJavaStyleIdentifiers; } public boolean propertyAccessType() { @@ -1386,9 +1453,17 @@ public class EntityGenerator { return this.collectionTypeName; } public void setCollectionTypeName(String collectionTypeName) { + this.checkRequiredString(collectionTypeName, "collection type name is required"); //$NON-NLS-1$ this.collectionTypeName = collectionTypeName; } + public String getCollectionAttributeNameSuffix() { + return this.collectionAttributeNameSuffix; + } + public void setCollectionAttributeNameSuffix(String collectionAttributeNameSuffix) { + this.collectionAttributeNameSuffix = collectionAttributeNameSuffix; + } + public int getFieldVisibility() { return this.fieldVisibility; } @@ -1401,19 +1476,19 @@ public class EntityGenerator { this.fieldVisibility = fieldVisibility; break; default: - throw new IllegalArgumentException("invalid field visibility: " + fieldVisibility); + throw new IllegalArgumentException("invalid field visibility: " + fieldVisibility); //$NON-NLS-1$ } } - String fieldVisibility() { + String getFieldVisibilityClause() { switch (this.fieldVisibility) { case PRIVATE: - return "private"; + return "private"; //$NON-NLS-1$ case PACKAGE: - return ""; + return ""; //$NON-NLS-1$ case PROTECTED: - return "protected"; + return "protected"; //$NON-NLS-1$ default: - throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility); + throw new IllegalStateException("invalid field visibility: " + this.fieldVisibility); //$NON-NLS-1$ } } @@ -1428,17 +1503,17 @@ public class EntityGenerator { this.methodVisibility = methodVisibility; break; default: - throw new IllegalArgumentException("invalid method visibility: " + methodVisibility); + throw new IllegalArgumentException("invalid method visibility: " + methodVisibility); //$NON-NLS-1$ } } - String methodVisibility() { + String getMethodVisibilityClause() { switch (this.methodVisibility) { case PROTECTED: - return "protected"; + return "protected"; //$NON-NLS-1$ case PUBLIC: - return "public"; + return "public"; //$NON-NLS-1$ default: - throw new IllegalStateException("invalid method visibility: " + this.methodVisibility); + throw new IllegalStateException("invalid method visibility: " + this.methodVisibility); //$NON-NLS-1$ } } @@ -1484,30 +1559,81 @@ public class EntityGenerator { this.generateEmbeddedIdForCompoundPK = ! generateIdClassForCompoundPK; } - /** - * key = table - * value = user-supplied override entity name - */ - public String getOverrideEntityName(Table table) { - return this.overrideEntityNames.get(table); + public String getEmbeddedIdAttributeName() { + return this.embeddedIdAttributeName; + } + public void setEmbeddedIdAttributeName(String embeddedIdAttributeName) { + this.checkRequiredString(embeddedIdAttributeName, "EmbeddedId attribute name is required"); //$NON-NLS-1$ + this.embeddedIdAttributeName = embeddedIdAttributeName; + } + + public String getPrimaryKeyMemberClassName() { + return this.primaryKeyMemberClassName; + } + public void setPrimaryKeyMemberClassName(String primaryKeyMemberClassName) { + this.checkRequiredString(primaryKeyMemberClassName, "primary key member class name is required"); //$NON-NLS-1$ + this.primaryKeyMemberClassName = primaryKeyMemberClassName; + } + + String getEntityName(Table table) { + return this.tables.get(table); } - public void setOverrideEntityName(Table table, String overrideEntityName) { - this.overrideEntityNames.put(table, overrideEntityName); + Iterator<Table> tables() { + return this.tables.keySet().iterator(); } - public void clearOverrideEntityNames() { - this.overrideEntityNames.clear(); + int tablesSize() { + return this.tables.size(); } - public void setOverrideEntityNames(Map<Table, String> overrideEntityNames) { - this.clearOverrideEntityNames(); - for (Map.Entry<Table, String> entry : overrideEntityNames.entrySet()) { - this.setOverrideEntityName(entry.getKey(), entry.getValue()); + public void addTable(Table table, String entityName) { + if (table == null) { + throw new NullPointerException("table is required"); //$NON-NLS-1$ + } + this.checkRequiredString(entityName, "entity name is required"); //$NON-NLS-1$ + if (this.tables.containsKey(table)) { + throw new IllegalArgumentException("duplicate table: " + table.getName()); //$NON-NLS-1$ + } + if (this.tables.values().contains(entityName)) { + throw new IllegalArgumentException("duplicate entity name: " + entityName); //$NON-NLS-1$ + } + if ( ! NameTools.stringConsistsOfJavaIdentifierCharacters(entityName)) { + throw new IllegalArgumentException("entity name is not a valid Java identifier: " + entityName); //$NON-NLS-1$ + } + if (NameTools.JAVA_RESERVED_WORDS_SET.contains(entityName)) { + throw new IllegalArgumentException("entity name is a Java reserved word: " + entityName); //$NON-NLS-1$ + } + this.tables.put(table, entityName); + } + + 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; + } + + public OverwriteConfirmer getOverwriteConfirmer() { + return this.overwriteConfirmer; + } + public void setOverwriteConfirmer(OverwriteConfirmer overwriteConfirmer) { + if (overwriteConfirmer == null) { + throw new NullPointerException("overwrite confirmer is required"); //$NON-NLS-1$ + } + this.overwriteConfirmer = overwriteConfirmer; + } + + private void checkRequiredString(String string, String message) { + if ((string == null) || (string.length() == 0)) { + throw new IllegalArgumentException(message); } } } - // ********** config ********** + // ********** overwrite confirmer ********** public static interface OverwriteConfirmer { /** @@ -1515,6 +1641,140 @@ public class EntityGenerator { * 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$ + } + } + + } + + + // ********** annotation name builder ********** + + /** + * Provide a pluggable way to determine whether and how the entity generator + * prints the names of various database objects. + */ + public static 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/internal/GenScope.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java index a0bb794687..09a74fb3bc 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenScope.java @@ -9,167 +9,179 @@ ******************************************************************************/ package org.eclipse.jpt.gen.internal; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; -import java.util.Set; + import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jpt.db.Table; import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +/** + * Build a GenTable for each db.Table passed in. + * Determine all the relations among the tables in the scope: + * many-to-many + * many-to-one + * one-to-many + * Make a first pass to determine each entity table's Java attribute names, + * because we will need them on subsequent passes. + */ class GenScope { - private final Map<Table, GenTable> genTables = new HashMap<Table, GenTable>(); + private final EntityGenerator.Config entityConfig; + private final HashMap<Table, GenTable> genTables; + - private IProgressMonitor progressMonitor; - // ********** construction/initialization ********** - GenScope(Collection<Table> tables, EntityGenerator.Config entityConfig, IProgressMonitor progressMonitor) { + GenScope(EntityGenerator.Config entityConfig, IProgressMonitor progressMonitor) { super(); - this.initialize(tables, entityConfig, progressMonitor); - } + this.entityConfig = entityConfig; + this.genTables = new HashMap<Table, GenTable>(entityConfig.tablesSize()); + SubMonitor sm = SubMonitor.convert(progressMonitor, JptGenMessages.GenScope_taskName, 4); - private void checkCanceled() { - if (this.progressMonitor.isCanceled()) { - throw new OperationCanceledException(); - } - } - - private void initialize(Collection<Table> tables, EntityGenerator.Config entityConfig, IProgressMonitor monitor) { - this.progressMonitor = monitor; - this.buildGenTables(tables, entityConfig); - checkCanceled(); - this.configureManyToManyRelations(); - checkCanceled(); - this.configureManyToOneRelations(); - checkCanceled(); - this.configureFieldNames(); - checkCanceled(); - } + this.buildGenTables(); + sm.worked(1); + this.checkCanceled(sm); - private void buildGenTables(Collection<Table> tables, EntityGenerator.Config entityConfig) { - int size = tables.size(); - // pass around a growing list of the entity names so we can avoid duplicates - Set<String> entityNames = new HashSet<String>(size); - for (Table table : tables) { - this.buildGenTable(table, entityConfig, entityNames); - this.progressMonitor.worked(40/size); - } + this.buildManyToManyRelations(); + sm.worked(1); + this.checkCanceled(sm); + + this.buildManyToOneRelations(); // this will also build the corresponding one-to-many relations + sm.worked(1); + this.checkCanceled(sm); + + this.buildAttributeNames(); + sm.worked(1); + this.checkCanceled(sm); } - private void buildGenTable(Table table, EntityGenerator.Config entityConfig, Collection<String> entityNames) { - this.genTables.put(table, new GenTable(this, table, entityConfig, entityNames)); + private void buildGenTables() { + for (Iterator<Table> stream = entityConfig.tables(); stream.hasNext(); ) { + Table table = stream.next(); + this.genTables.put(table, new GenTable(this, table)); + } } /** * find all the "join" tables */ - private void configureManyToManyRelations() { - int tablesSize = CollectionTools.size(this.tables()); - - //first time takes the longest, should we take that into account? - for (Iterator<GenTable> stream = this.tables(); stream.hasNext(); ) { - checkCanceled(); - stream.next().configureManyToManyRelations(); - this.progressMonitor.worked(730/tablesSize); + private void buildManyToManyRelations() { + for (Iterator<GenTable> stream = this.genTables(); stream.hasNext(); ) { + stream.next().buildJoinTableRelation(); } + // revert any "join" table that is referenced by another table back to an "entity" table - Set<GenTable> referencedTables = this.buildReferencedTables(); - tablesSize = CollectionTools.size(this.joinTables()); - for (Iterator<GenTable> stream = this.joinTables(); stream.hasNext(); ) { + HashSet<GenTable> referencedGenTables = this.buildReferencedGenTables(); + for (Iterator<GenTable> stream = this.joinGenTables(); stream.hasNext(); ) { GenTable joinGenTable = stream.next(); - if (referencedTables.contains(joinGenTable)) { + if (referencedGenTables.contains(joinGenTable)) { joinGenTable.clearJoinTableRelation(); } - this.progressMonitor.worked(40/tablesSize); } } /** - * find all the many-to-one and one-to-many relations + * find all the many-to-one and corresponding one-to-many relations */ - private void configureManyToOneRelations() { - int tablesSize = CollectionTools.size(this.entityTables()); - for (Iterator<GenTable> stream = this.entityTables(); stream.hasNext(); ) { - stream.next().configureManyToOneRelations(); - this.progressMonitor.worked(50/tablesSize); + private void buildManyToOneRelations() { + for (Iterator<GenTable> stream = this.entityGenTables(); stream.hasNext(); ) { + stream.next().buildManyToOneRelations(); } } /** - * determine all the Java field names up-front because we will + * determine all the Java attribute names up-front because we will * need them for things like 'mappedBy' annotation elements */ - private void configureFieldNames() { - int tablesSize = CollectionTools.size(this.entityTables()); - for (Iterator<GenTable> stream = this.entityTables(); stream.hasNext(); ) { - stream.next().configureFieldNames(); - this.progressMonitor.worked(50/tablesSize); + private void buildAttributeNames() { + for (Iterator<GenTable> stream = this.entityGenTables(); stream.hasNext(); ) { + stream.next().buildAttributeNames(); } } // ********** package API ********** + EntityGenerator.Config getEntityConfig() { + return this.entityConfig; + } + /** * return only the gen tables that are suitable for generating * entities (i.e. exclude the "join" tables) */ - Iterator<GenTable> entityTables() { - return new FilteringIterator<GenTable, GenTable>(this.tables()) { + Iterator<GenTable> entityGenTables() { + return new FilteringIterator<GenTable, GenTable>(this.genTables()) { @Override - protected boolean accept(GenTable next) { - return ! next.isJoinTable(); + protected boolean accept(GenTable genTable) { + return ! genTable.isJoinTable(); } }; } - int numEntityTables() { - return CollectionTools.size(entityTables()); + int entityTablesSize() { + return CollectionTools.size(this.entityGenTables()); } - + /** - * return the gen table corresponding to the specified table + * return the gen table corresponding to the specified db table; + * return null if the gen table is not "in-scope" (e.g. a db foreign key + * might have a reference to a db table that was not included in the + * scope, so we won't have a corresponding gen table) */ - GenTable genTable(Table table) { + GenTable getGenTable(Table table) { return this.genTables.get(table); } - // ********** internal API ********** + // ********** internal methods ********** - private Iterator<GenTable> tables() { + private Iterator<GenTable> genTables() { return this.genTables.values().iterator(); } + private int genTablesSize() { + return this.genTables.size(); + } + /** * return only the "join" gen tables */ - private Iterator<GenTable> joinTables() { - return new FilteringIterator<GenTable, GenTable>(this.tables()) { + private Iterator<GenTable> joinGenTables() { + return new FilteringIterator<GenTable, GenTable>(this.genTables()) { @Override - protected boolean accept(GenTable next) { - return next.isJoinTable(); + protected boolean accept(GenTable genTable) { + return genTable.isJoinTable(); } }; } /** - * build a set of the tables that are referenced by other tables + * build a set of the gen tables that are referenced by other gen tables * in the scope */ - private Set<GenTable> buildReferencedTables() { - int size = CollectionTools.size(this.tables()); - Set<GenTable> referencedTables = new HashSet<GenTable>(this.genTables.size()); - for (Iterator<GenTable> stream = this.tables(); stream.hasNext(); ) { - stream.next().addReferencedTablesTo(referencedTables); - this.progressMonitor.worked(20/size); + private HashSet<GenTable> buildReferencedGenTables() { + HashSet<GenTable> referencedGenTables = new HashSet<GenTable>(this.genTablesSize()); + for (Iterator<GenTable> stream = this.genTables(); stream.hasNext(); ) { + stream.next().addReferencedGenTablesTo(referencedGenTables); } - return referencedTables; + return referencedGenTables; + } + + private void checkCanceled(IProgressMonitor progressMonitor) { + if (progressMonitor.isCanceled()) { + throw new OperationCanceledException(); + } + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.genTables); } } diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java index 395a51b94e..52e26086db 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/GenTable.java @@ -14,7 +14,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; import java.util.Set; import org.eclipse.jpt.db.Column; @@ -27,91 +26,88 @@ import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; /** * associate a table with the various relations that will be used when - * generating the entity + * generating the entity corresponding to the table */ class GenTable { private final GenScope scope; private final Table table; - private final EntityGenerator.Config entityConfig; - private final String entityName; - private ManyToManyRelation joinTableRelation; - private Collection<ManyToManyRelation> ownedManyToManyRelations = new ArrayList<ManyToManyRelation>(); - private Collection<ManyToManyRelation> nonOwnedManyToManyRelations = new ArrayList<ManyToManyRelation>(); - private Collection<ManyToOneRelation> manyToOneRelations = new ArrayList<ManyToOneRelation>(); - private Collection<OneToManyRelation> oneToManyRelations = new ArrayList<OneToManyRelation>(); - private Set<Column> foreignKeyColumns = new HashSet<Column>(); - - // key=column/relation; value=name - private final Map<Object, String> fieldNames = new HashMap<Object, String>(); + // these relations cannot be built until after we have built all the scope's tables + private ManyToManyRelation joinTableRelation; + private final ArrayList<ManyToManyRelation> ownedManyToManyRelations = new ArrayList<ManyToManyRelation>(); + private final ArrayList<ManyToManyRelation> nonOwnedManyToManyRelations = new ArrayList<ManyToManyRelation>(); + private final ArrayList<ManyToOneRelation> manyToOneRelations = new ArrayList<ManyToOneRelation>(); + private final ArrayList<OneToManyRelation> oneToManyRelations = new ArrayList<OneToManyRelation>(); + private final HashSet<Column> foreignKeyColumns = new HashSet<Column>(); + + // key=column/relation; value=entity attribute (field/property) name + private final HashMap<Object, String> attributeNames = new HashMap<Object, String>(); + // key to 'attributeNames' for the optional embedded ID attribute name private static final Object EMBEDDED_ID_VIRTUAL_COLUMN = new Object(); // ********** construction/initialization ********** - GenTable(GenScope scope, Table table, EntityGenerator.Config entityConfig, Collection<String> entityNames) { + GenTable(GenScope scope, Table table) { super(); this.scope = scope; this.table = table; - this.entityConfig = entityConfig; - this.entityName = this.buildEntityName(entityNames); - } - - private String buildEntityName(Collection<String> entityNames) { - String name = this.table.getShortJavaClassName(); - String overrideEntityName = this.entityConfig.getOverrideEntityName(this.table); - if (overrideEntityName == null) { - if (this.entityConfig.convertToCamelCase()) { - // camel-casing can convert a name back to a reserved word (e.g. "package_" -> "package") - name = NameTools.convertToJavaIdentifier(StringTools.convertUnderscoresToCamelCase(name)); - } - } else { - name = overrideEntityName; - } - name = NameTools.uniqueNameForIgnoreCase(name, entityNames); - entityNames.add(name); - return name; } // ********** package API ********** + EntityGenerator.Config getEntityConfig() { + return this.scope.getEntityConfig(); + } + /** - * determine whether the table is a "join" table within the table's scope + * determine whether the table is a "join" table within the table's scope; + * this can be removed, later, if we find another table references the, + * seemingly, join table + * @see #clearJoinTableRelation() (and callers) */ - void configureManyToManyRelations() { - if (this.table.foreignKeysSize() != 2) { - // the table must have exactly 2 foreign keys - return; + void buildJoinTableRelation() { + if ( ! this.table.isPossibleJoinTable()) { + return; // the table must have exactly 2 foreign keys } - for (Iterator<Column> stream = this.table.columns(); stream.hasNext(); ) { - if ( ! this.table.foreignKeyBaseColumnsContains(stream.next())) { - // all the table's columns must belong to one (or both) of the 2 foreign keys - return; - } + ForeignKey owningFK = this.table.getJoinTableOwningForeignKey(); + GenTable owningGenTable = this.scope.getGenTable(owningFK.getReferencedTable()); + if (owningGenTable == null) { + return; // both tables must be in the scope } - Iterator<ForeignKey> fKeys = this.table.foreignKeys(); - ForeignKey owningFK = fKeys.next(); - ForeignKey nonOwningFK = fKeys.next(); - GenTable owningTable = this.scope.genTable(owningFK.getReferencedTable()); - GenTable nonOwningTable = this.scope.genTable(nonOwningFK.getReferencedTable()); - if ((owningTable == null) || (nonOwningTable == null)) { - // both tables must be in the scope - return; + ForeignKey nonOwningFK = this.table.getJoinTableNonOwningForeignKey(); + GenTable nonOwningGenTable = this.scope.getGenTable(nonOwningFK.getReferencedTable()); + if (nonOwningGenTable == null) { + return; // both tables must be in the scope } - this.joinTableRelation = new ManyToManyRelation(this, owningFK, owningTable, nonOwningFK, nonOwningTable); + this.joinTableRelation = new ManyToManyRelation( + this, + owningFK, + owningGenTable, + nonOwningFK, + nonOwningGenTable + ); } - void addReferencedTablesTo(Set<GenTable> referencedTables) { + /** + * used by the scope to figure out whether "join" tables should be + * converted to "entity" tables + */ + void addReferencedGenTablesTo(Set<GenTable> referencedTables) { for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) { ForeignKey fk = stream.next(); - GenTable genTable = this.scope.genTable(fk.getReferencedTable()); + GenTable genTable = this.scope.getGenTable(fk.getReferencedTable()); if (genTable != null) { referencedTables.add(genTable); } } } + /** + * the scope clears the join table relation if there are any references + * to the join table from other tables in the scope + */ void clearJoinTableRelation() { this.joinTableRelation.clear(); this.joinTableRelation = null; @@ -120,34 +116,38 @@ class GenTable { /** * find "in-scope" foreign keys */ - void configureManyToOneRelations() { + void buildManyToOneRelations() { for (Iterator<ForeignKey> stream = this.table.foreignKeys(); stream.hasNext(); ) { ForeignKey fk = stream.next(); - GenTable referencedtable = this.scope.genTable(fk.getReferencedTable()); - if (referencedtable == null) { - continue; // skip to next FK + GenTable referencedGenTable = this.scope.getGenTable(fk.getReferencedTable()); + if (referencedGenTable != null) { + this.manyToOneRelations.add(new ManyToOneRelation(this, fk, referencedGenTable)); } - this.manyToOneRelations.add(new ManyToOneRelation(this, fk, referencedtable)); } } /** * now that all the relations are in place, we can configure the Java - * field names + * attribute names */ - void configureFieldNames() { - Set<Column> columns = CollectionTools.set(this.table.columns()); - if ((this.table.primaryKeyColumnsSize() > 1) && this.entityConfig.generateEmbeddedIdForCompoundPK()) { - // if we are going to generate an EmbeddedId field, add it to - // 'fieldNames' so we don't collide with it later, when generating - // field names for the columns etc. - this.configureFieldName(EMBEDDED_ID_VIRTUAL_COLUMN, "pk"); + void buildAttributeNames() { + if ((this.table.primaryKeyColumnsSize() > 1) && this.getEntityConfig().generateEmbeddedIdForCompoundPK()) { + // if we are going to generate an EmbeddedId attribute, add it to + // 'attributeNames' so we don't collide with it later, when generating + // attribute names for the columns etc. + this.configureAttributeName(EMBEDDED_ID_VIRTUAL_COLUMN, this.getEntityConfig().getEmbeddedIdAttributeName()); } - this.configureManyToOneFieldNames(columns); - this.configureBasicFieldNames(columns); - this.configureOneToManyFieldNames(); - this.configureOwnedManyToManyFieldNames(); - this.configureNonOwnedManyToManyFieldNames(); + + // gather up all the table's columns... + Set<Column> columns = CollectionTools.set(this.table.columns(), this.table.columnsSize()); + // ...remove the columns that belong exclusively to many-to-one foreign keys... + this.buildManyToOneAttributeNames(columns); + // ...and use the remaining columns to generate "basic" attribute names + this.buildBasicAttributeNames(columns); + + this.buildOneToManyAttributeNames(); + this.buildOwnedManyToManyAttributeNames(); + this.buildNonOwnedManyToManyAttributeNames(); } /** @@ -157,8 +157,8 @@ class GenTable { Iterator<Column> readOnlyPrimaryKeyColumns() { return new FilteringIterator<Column, Column>(this.table.primaryKeyColumns()) { @Override - protected boolean accept(Column column) { - return GenTable.this.foreignKeyColumnsContains(column); + protected boolean accept(Column pkColumn) { + return pkColumn.isForeignKeyColumn(); } }; } @@ -170,8 +170,8 @@ class GenTable { Iterator<Column> writablePrimaryKeyColumns() { return new FilteringIterator<Column, Column>(this.table.primaryKeyColumns()) { @Override - protected boolean accept(Column column) { - return ! GenTable.this.foreignKeyColumnsContains(column); + protected boolean accept(Column pkColumn) { + return ! pkColumn.isForeignKeyColumn(); } }; } @@ -184,8 +184,7 @@ class GenTable { return new FilteringIterator<Column, Column>(this.table.columns()) { @Override protected boolean accept(Column column) { - return ! (GenTable.this.primaryKeyColumnsContains(column) - || GenTable.this.foreignKeyColumnsContains(column)); + return ! (column.isPrimaryKeyColumn() || column.isForeignKeyColumn()); } }; } @@ -195,7 +194,7 @@ class GenTable { } String getEntityName() { - return this.entityName; + return this.getEntityConfig().getEntityName(this.table); } boolean isJoinTable() { @@ -222,10 +221,6 @@ class GenTable { this.oneToManyRelations.add(relation); } - String javaFieldName() { - return this.table.getJavaFieldName(); - } - Iterator<ManyToOneRelation> manyToOneRelations() { return this.manyToOneRelations.iterator(); } @@ -243,103 +238,111 @@ class GenTable { } /** - * the key can be a column or relation + * the key can be a column or relation or #EMBEDDED_ID_VIRTUAL_COLUMN */ - private String fieldNameForInternal(Object o) { - return this.fieldNames.get(o); + private String getAttributeNameFor_(Object o) { + return this.attributeNames.get(o); } /** - * this will return null if we don't want an embedded id field + * this will return null if we don't want an embedded id attribute */ - String fieldNameForEmbeddedId() { - return this.fieldNameForInternal(EMBEDDED_ID_VIRTUAL_COLUMN); + String getAttributeNameForEmbeddedId() { + return this.getAttributeNameFor_(EMBEDDED_ID_VIRTUAL_COLUMN); } - String fieldNameFor(Column column) { - return this.fieldNameForInternal(column); + String getAttributeNameFor(Column column) { + return this.getAttributeNameFor_(column); } - String fieldNameFor(ManyToOneRelation relation) { - return this.fieldNameForInternal(relation); + String getAttributeNameFor(ManyToOneRelation relation) { + return this.getAttributeNameFor_(relation); } - String fieldNameFor(OneToManyRelation relation) { - return this.fieldNameForInternal(relation); + String getAttributeNameFor(OneToManyRelation relation) { + return this.getAttributeNameFor_(relation); } - String fieldNameFor(ManyToManyRelation relation) { - return this.fieldNameForInternal(relation); + String getAttributeNameFor(ManyToManyRelation relation) { + return this.getAttributeNameFor_(relation); } - String name() { + String getName() { return this.table.getName(); } + boolean joinTableNameIsDefault() { + return this.table.joinTableNameIsDefault(); + } + // ********** internal API ********** /** - * while we are figuring out the names for the m:1 fields, remove from the + * while we are figuring out the names for the m:1 attributes, remove from the * specified set of columns the columns that are only part of the foreign keys + * (leaving the remaining columns for basic attributes) */ - private void configureManyToOneFieldNames(Set<Column> columns) { + private void buildManyToOneAttributeNames(Set<Column> columns) { for (ManyToOneRelation relation : this.manyToOneRelations) { CollectionTools.removeAll(columns, relation.getForeignKey().nonPrimaryKeyBaseColumns()); CollectionTools.addAll(this.foreignKeyColumns, relation.getForeignKey().baseColumns()); - relation.setMappedBy(this.configureFieldName(relation, relation.javaFieldName())); + relation.setMappedBy(this.configureAttributeName(relation, relation.getAttributeName())); } } - private String configureFieldName(Object o, String fieldName) { - fieldName = this.camelCaseFieldName(fieldName); - fieldName = NameTools.uniqueNameFor(fieldName, this.fieldNames.values()); - this.fieldNames.put(o, fieldName); - return fieldName; - } - - private String camelCaseFieldName(String name) { - return this.entityConfig.convertToCamelCase() ? - // camel-casing can convert a name back to a reserved word (e.g. "package_" -> "package") - NameTools.convertToJavaIdentifier(StringTools.convertUnderscoresToCamelCase(name, false)) // false = don't capitalize first letter - : - name; - } - /** - * build a unique field name for the specified "basic" columns, + * build a unique attribute name for the specified "basic" columns, * checking for name collisions */ - private void configureBasicFieldNames(Set<Column> columns) { + private void buildBasicAttributeNames(Set<Column> columns) { for (Column column : columns) { - this.configureFieldName(column, column.getJavaFieldName()); + this.configureAttributeName(column, column.getName()); } } - private void configureOneToManyFieldNames() { + private void buildOneToManyAttributeNames() { for (OneToManyRelation relation : this.oneToManyRelations) { - this.configureFieldName(relation, relation.javaFieldName()); + this.configureAttributeName(relation, relation.getJavaAttributeName()); } } - private void configureOwnedManyToManyFieldNames() { + private void buildOwnedManyToManyAttributeNames() { for (ManyToManyRelation relation : this.ownedManyToManyRelations) { - relation.setMappedBy(this.configureFieldName(relation, relation.javaFieldNameFor(this))); + relation.setMappedBy(this.configureAttributeName(relation, relation.getOwnedJavaAttributeName())); } } - private void configureNonOwnedManyToManyFieldNames() { + private void buildNonOwnedManyToManyAttributeNames() { for (ManyToManyRelation relation : this.nonOwnedManyToManyRelations) { - this.configureFieldName(relation, relation.javaFieldNameFor(this)); + this.configureAttributeName(relation, relation.getNonOwnedJavaAttributeName()); } } - boolean foreignKeyColumnsContains(Column column) { - return this.foreignKeyColumns.contains(column); + /** + * Convert the specified attribute name to something unique for the entity, + * converting it to something Java-like if the config flag is set. + * Store the calculated name so we can get it back later, when we + * are generating source. + */ + private String configureAttributeName(Object o, String attributeName) { + String result = attributeName; + Collection<String> existingAttributeNames = this.attributeNames.values(); + if (this.getEntityConfig().convertToJavaStyleIdentifiers()) { + result = EntityGenTools.convertToUniqueJavaStyleAttributeName(result, existingAttributeNames); + } else { + // first, convert the attribute name to a legal Java identifier + result = NameTools.convertToJavaIdentifier(result); + // then make sure it's unique + result = NameTools.uniqueNameForIgnoreCase(attributeName, existingAttributeNames); + } + this.attributeNames.put(o, result); + return result; } - boolean primaryKeyColumnsContains(Column column) { - return this.table.primaryKeyColumnsContains(column); + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.table); } } diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JPA.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JPA.java new file mode 100644 index 0000000000..7f601e4253 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JPA.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package org.eclipse.jpt.gen.internal; + + +/** + * JPA Java-related stuff (annotations etc.) + * + * Provisional API: This interface is part of an interim API that is still + * under development and expected to change significantly before reaching + * stability. It is available at this early stage to solicit feedback from + * pioneering adopters on the understanding that any code that uses this API + * will almost certainly be broken (repeatedly) as the API evolves. + */ +// TODO move to utility? +@SuppressWarnings("nls") +public interface JPA { + + // JPA package + String PACKAGE = "javax.persistence"; + String PACKAGE_ = PACKAGE + '.'; + + + // ********** API ********** + + // JPA annotations + String ASSOCIATION_OVERRIDE = PACKAGE_ + "AssociationOverride"; + String ASSOCIATION_OVERRIDE__NAME = "name"; + String ASSOCIATION_OVERRIDE__JOIN_COLUMNS = "joinColumns"; + String ASSOCIATION_OVERRIDES = PACKAGE_ + "AssociationOverrides"; + String ASSOCIATION_OVERRIDES__VALUE = "value"; + String ATTRIBUTE_OVERRIDE = PACKAGE_ + "AttributeOverride"; + String ATTRIBUTE_OVERRIDE__NAME = "name"; + String ATTRIBUTE_OVERRIDE__COLUMN = "column"; + String ATTRIBUTE_OVERRIDES = PACKAGE_ + "AttributeOverrides"; + String ATTRIBUTE_OVERRIDES__VALUE = "value"; + String BASIC = PACKAGE_ + "Basic"; + String BASIC__FETCH = "fetch"; + String BASIC__OPTIONAL = "optional"; + String COLUMN = PACKAGE_ + "Column"; + String COLUMN__NAME = "name"; + String COLUMN__UNIQUE = "unique"; + String COLUMN__NULLABLE = "nullable"; + String COLUMN__INSERTABLE = "insertable"; + String COLUMN__UPDATABLE = "updatable"; + String COLUMN__COLUMN_DEFINITION = "columnDefinition"; + String COLUMN__TABLE = "table"; + String COLUMN__LENGTH = "length"; + String COLUMN__PRECISION = "precision"; + String COLUMN__SCALE = "scale"; + String COLUMN_RESULT = PACKAGE_ + "ColumnResult"; + String COLUMN_RESULT__NAME = "name"; + String DISCRIMINATOR_COLUMN = PACKAGE_ + "DiscriminatorColumn"; + String DISCRIMINATOR_COLUMN__NAME = "name"; + String DISCRIMINATOR_COLUMN__DISCRIMINATOR_TYPE = "discriminatorType"; + String DISCRIMINATOR_COLUMN__COLUMN_DEFINITION = "columnDefinition"; + String DISCRIMINATOR_COLUMN__LENGTH = "length"; + String DISCRIMINATOR_VALUE = PACKAGE_ + "DiscriminatorValue"; + String DISCRIMINATOR_VALUE__VALUE = "value"; + String EMBEDDABLE = PACKAGE_ + "Embeddable"; + String EMBEDDED = PACKAGE_ + "Embedded"; + String EMBEDDED_ID = PACKAGE_ + "EmbeddedId"; + String ENTITY = PACKAGE_ + "Entity"; + String ENTITY__NAME = "name"; + String ENTITY_LISTENERS = PACKAGE_ + "EntityListeners"; + String ENTITY_LISTENERS__VALUE = "value"; + String ENTITY_RESULT = PACKAGE_ + "EntityResult"; + String ENTITY_RESULT__ENTITY_CLASS = "entityClass"; + String ENTITY_RESULT__FIELDS = "fields"; + String ENTITY_RESULT__DISCRIMINATOR_COLUMN = "discriminatorColumn"; + String ENUMERATED = PACKAGE_ + "Enumerated"; + String ENUMERATED__VALUE = "value"; + String EXCLUDE_DEFAULT_LISTENERS = PACKAGE_ + "ExcludeDefaultListeners"; + String EXCLUDE_SUPERCLASS_LISTENERS = PACKAGE_ + "ExcludeSuperclassListeners"; + String FIELD_RESULT = PACKAGE_ + "FieldResult"; + String FIELD_RESULT__NAME = "name"; + String FIELD_RESULT__COLUMN = "column"; + String FLUSH_MODE = PACKAGE_ + "FlushMode"; + String FLUSH_MODE__VALUE = "value"; + String GENERATED_VALUE = PACKAGE_ + "GeneratedValue"; + String GENERATED_VALUE__STRATEGY = "strategy"; + String GENERATED_VALUE__GENERATOR = "generator"; + String ID = PACKAGE_ + "Id"; + String ID_CLASS = PACKAGE_ + "IdClass"; + String ID_CLASS__VALUE = "value"; + String INHERITANCE = PACKAGE_ + "Inheritance"; + String INHERITANCE__STRATEGY = "strategy"; + String JOIN_COLUMN = PACKAGE_ + "JoinColumn"; + String JOIN_COLUMN__NAME = "name"; + String JOIN_COLUMN__REFERENCED_COLUMN_NAME = "referencedColumnName"; + String JOIN_COLUMN__UNIQUE = "unique"; + String JOIN_COLUMN__NULLABLE = "nullable"; + String JOIN_COLUMN__INSERTABLE = "insertable"; + String JOIN_COLUMN__UPDATABLE = "updatable"; + String JOIN_COLUMN__COLUMN_DEFINITION = "columnDefinition"; + String JOIN_COLUMN__TABLE = "table"; + String JOIN_COLUMNS = PACKAGE_ + "JoinColumns"; + String JOIN_COLUMNS__VALUE = "value"; + String JOIN_TABLE = PACKAGE_ + "JoinTable"; + String JOIN_TABLE__NAME = "name"; + String JOIN_TABLE__CATALOG = "catalog"; + String JOIN_TABLE__SCHEMA = "schema"; + String JOIN_TABLE__JOIN_COLUMNS = "joinColumns"; + String JOIN_TABLE__INVERSE_JOIN_COLUMNS = "inverseJoinColumns"; + String JOIN_TABLE__UNIQUE_CONSTRAINTS = "uniqueConstraints"; + String LOB = PACKAGE_ + "Lob"; + String MANY_TO_MANY = PACKAGE_ + "ManyToMany"; + String MANY_TO_MANY__TARGET_ENTITY = "targetEntity"; + String MANY_TO_MANY__CASCADE = "cascade"; + String MANY_TO_MANY__FETCH = "fetch"; + String MANY_TO_MANY__MAPPED_BY = "mappedBy"; + String MANY_TO_ONE = PACKAGE_ + "ManyToOne"; + String MANY_TO_ONE__TARGET_ENTITY = "targetEntity"; + String MANY_TO_ONE__CASCADE = "cascade"; + String MANY_TO_ONE__FETCH = "fetch"; + String MANY_TO_ONE__OPTIONAL = "optional"; + String MAP_KEY = PACKAGE_ + "MapKey"; + String MAP_KEY__NAME = "name"; + String MAPPED_SUPERCLASS = PACKAGE_ + "MappedSuperclass"; + String NAMED_NATIVE_QUERIES = PACKAGE_ + "NamedNativeQueries"; + String NAMED_NATIVE_QUERIES__VALUE = "value"; + String NAMED_NATIVE_QUERY = PACKAGE_ + "NamedNativeQuery"; + String NAMED_NATIVE_QUERY__NAME = "name"; + String NAMED_NATIVE_QUERY__QUERY = "query"; + String NAMED_NATIVE_QUERY__HINTS = "hints"; + String NAMED_NATIVE_QUERY__RESULT_CLASS = "resultClass"; + String NAMED_NATIVE_QUERY__RESULT_SET_MAPPING = "resultSetMapping"; + String NAMED_QUERIES = PACKAGE_ + "NamedQueries"; + String NAMED_QUERIES__VALUE = "value"; + String NAMED_QUERY = PACKAGE_ + "NamedQuery"; + String NAMED_QUERY__NAME = "name"; + String NAMED_QUERY__QUERY = "query"; + String NAMED_QUERY__HINTS = "hints"; + String ONE_TO_MANY = PACKAGE_ + "OneToMany"; + String ONE_TO_MANY__TARGET_ENTITY = "targetEntity"; + String ONE_TO_MANY__CASCADE = "cascade"; + String ONE_TO_MANY__FETCH = "fetch"; + String ONE_TO_MANY__MAPPED_BY = "mappedBy"; + String ONE_TO_ONE = PACKAGE_ + "OneToOne"; + String ONE_TO_ONE__TARGET_ENTITY = "targetEntity"; + String ONE_TO_ONE__CASCADE = "cascade"; + String ONE_TO_ONE__FETCH = "fetch"; + String ONE_TO_ONE__OPTIONAL = "optional"; + String ONE_TO_ONE__MAPPED_BY = "mappedBy"; + String ORDER_BY = PACKAGE_ + "OrderBy"; + String ORDER_BY__VALUE = "value"; + String PERSISTENCE_CONTEXT = PACKAGE_ + "PersistenceContext"; + String PERSISTENCE_CONTEXT__NAME = "name"; + String PERSISTENCE_CONTEXT__UNIT_NAME = "unitName"; + String PERSISTENCE_CONTEXT__TYPE = "type"; + String PERSISTENCE_CONTEXTS = PACKAGE_ + "PersistenceContexts"; + String PERSISTENCE_CONTEXTS__VALUE = "value"; + String PERSISTENCE_UNIT = PACKAGE_ + "XmlPersistenceUnit"; + String PERSISTENCE_UNIT__NAME = "name"; + String PERSISTENCE_UNIT__UNIT_NAME = "unitName"; + String PERSISTENCE_UNITS = PACKAGE_ + "PersistenceUnits"; + String PERSISTENCE_UNITS__VALUE = "value"; + String POST_LOAD = PACKAGE_ + "PostLoad"; + String POST_PERSIST = PACKAGE_ + "PostPersist"; + String POST_REMOVE = PACKAGE_ + "PostRemove"; + String POST_UPDATE = PACKAGE_ + "PostUpdate"; + String PRE_PERSIST = PACKAGE_ + "PrePersist"; + String PRE_REMOVE = PACKAGE_ + "PreRemove"; + String PRE_UPDATE = PACKAGE_ + "PreUpdate"; + String PRIMARY_KEY_JOIN_COLUMN = PACKAGE_ + "PrimaryKeyJoinColumn"; + String PRIMARY_KEY_JOIN_COLUMN__NAME = "name"; + String PRIMARY_KEY_JOIN_COLUMN__REFERENCED_COLUMN_NAME = "referencedColumnName"; + String PRIMARY_KEY_JOIN_COLUMN__COLUMN_DEFINITION = "columnDefinition"; + String PRIMARY_KEY_JOIN_COLUMNS = PACKAGE_ + "PrimaryKeyJoinColumns"; + String PRIMARY_KEY_JOIN_COLUMNS__VALUE = "value"; + String QUERY_HINT = PACKAGE_ + "QueryHint"; + String QUERY_HINT__NAME = "name"; + String QUERY_HINT__VALUE = "value"; + String SECONDARY_TABLE = PACKAGE_ + "SecondaryTable"; + String SECONDARY_TABLE__NAME = "name"; + String SECONDARY_TABLE__CATALOG = "catalog"; + String SECONDARY_TABLE__SCHEMA = "schema"; + String SECONDARY_TABLE__PK_JOIN_COLUMNS = "pkJoinColumns"; + String SECONDARY_TABLE__UNIQUE_CONSTRAINTS = "uniqueConstraints"; + String SECONDARY_TABLES = PACKAGE_ + "SecondaryTables"; + String SECONDARY_TABLES__VALUE = "value"; + String SEQUENCE_GENERATOR = PACKAGE_ + "SequenceGenerator"; + String SEQUENCE_GENERATOR__NAME = "name"; + String SEQUENCE_GENERATOR__SEQUENCE_NAME = "sequenceName"; + String SEQUENCE_GENERATOR__INITIAL_VALUE = "initialValue"; + String SEQUENCE_GENERATOR__ALLOCATION_SIZE = "allocationSize"; + String SQL_RESULT_SET_MAPPING = PACKAGE_ + "SqlResultSetMapping"; + String SQL_RESULT_SET_MAPPING__NAME = "name"; + String SQL_RESULT_SET_MAPPING__ENTITIES = "entities"; + String SQL_RESULT_SET_MAPPING__COLUMNS = "columns"; + String TABLE = PACKAGE_ + "Table"; + String TABLE__NAME = "name"; + String TABLE__CATALOG = "catalog"; + String TABLE__SCHEMA = "schema"; + String TABLE__UNIQUE_CONSTRAINTS = "uniqueConstraints"; + String TABLE_GENERATOR = PACKAGE_ + "TableGenerator"; + String TABLE_GENERATOR__NAME = "name"; + String TABLE_GENERATOR__TABLE = "table"; + String TABLE_GENERATOR__CATALOG = "catalog"; + String TABLE_GENERATOR__SCHEMA = "schema"; + String TABLE_GENERATOR__PK_COLUMN_NAME = "pkColumnName"; + String TABLE_GENERATOR__VALUE_COLUMN_NAME = "valueColumnName"; + String TABLE_GENERATOR__PK_COLUMN_VALUE = "pkColumnValue"; + String TABLE_GENERATOR__INITIAL_VALUE = "initialValue"; + String TABLE_GENERATOR__ALLOCATION_SIZE = "allocationSize"; + String TABLE_GENERATOR__UNIQUE_CONSTRAINTS = "uniqueConstraints"; + String TEMPORAL = PACKAGE_ + "Temporal"; + String TEMPORAL__VALUE = "value"; + String TRANSIENT = PACKAGE_ + "Transient"; + String UNIQUE_CONSTRAINT = PACKAGE_ + "UniqueConstraint"; + String UNIQUE_CONSTRAINT__COLUMN_NAMES = "columnNames"; + String VERSION = PACKAGE_ + "Version"; + + // JPA enums + String GENERATION_TYPE = PACKAGE_ + "GenerationType"; + String GENERATION_TYPE_ = GENERATION_TYPE + '.'; + String GENERATION_TYPE__AUTO = GENERATION_TYPE_ + "AUTO"; + String GENERATION_TYPE__IDENTITY = GENERATION_TYPE_ + "IDENTITY"; + String GENERATION_TYPE__SEQUENCE = GENERATION_TYPE_ + "SEQUENCE"; + String GENERATION_TYPE__TABLE = GENERATION_TYPE_ + "TABLE"; + + String CASCADE_TYPE = PACKAGE_ + "CascadeType"; + String CASCADE_TYPE_ = CASCADE_TYPE + '.'; + String CASCADE_TYPE__ALL = CASCADE_TYPE_ + "ALL"; + String CASCADE_TYPE__MERGE = CASCADE_TYPE_ + "MERGE"; + String CASCADE_TYPE__PERSIST = CASCADE_TYPE_ + "PERSIST"; + String CASCADE_TYPE__REFRESH = CASCADE_TYPE_ + "REFRESH"; + String CASCADE_TYPE__REMOVE = CASCADE_TYPE_ + "REMOVE"; + + String DISCRIMINATOR_TYPE = PACKAGE_ + "DiscriminatorType"; + String DISCRIMINATOR_TYPE_ = DISCRIMINATOR_TYPE + '.'; + String DISCRIMINATOR_TYPE__CHAR = DISCRIMINATOR_TYPE_ + "CHAR"; + String DISCRIMINATOR_TYPE__INTEGER = DISCRIMINATOR_TYPE_ + "INTEGER"; + String DISCRIMINATOR_TYPE__STRING = DISCRIMINATOR_TYPE_ + "STRING"; + + String ENUM_TYPE = PACKAGE_ + "EnumType"; + String ENUM_TYPE_ = ENUM_TYPE + '.'; + String ENUM_TYPE__ORDINAL = ENUM_TYPE_ + "ORDINAL"; + String ENUM_TYPE__STRING = ENUM_TYPE_ + "STRING"; + + String FETCH_TYPE = PACKAGE_ + "FetchType"; + String FETCH_TYPE_ = FETCH_TYPE + '.'; + String FETCH_TYPE__EAGER = FETCH_TYPE_ + "EAGER"; + String FETCH_TYPE__LAZY = FETCH_TYPE_ + "LAZY"; + + String FLUSH_MODE_TYPE = PACKAGE_ + "FlushModeType"; + String FLUSH_MODE_TYPE_ = FLUSH_MODE_TYPE + '.'; + String FLUSH_MODE_TYPE__AUTO = FLUSH_MODE_TYPE_ + "AUTO"; + String FLUSH_MODE_TYPE__COMMIT = FLUSH_MODE_TYPE_ + "COMMIT"; + + String INHERITANCE_TYPE = PACKAGE_ + "InheritanceType"; + String INHERITANCE_TYPE_ = INHERITANCE_TYPE + '.'; + String INHERITANCE_TYPE__JOINED = INHERITANCE_TYPE_ + "JOINED"; + String INHERITANCE_TYPE__SINGLE_TABLE = INHERITANCE_TYPE_ + "SINGLE_TABLE"; + String INHERITANCE_TYPE__TABLE_PER_CLASS = INHERITANCE_TYPE_ + "TABLE_PER_CLASS"; + + String PERSISTENCE_CONTEXT_TYPE = PACKAGE_ + "PersistenceContextType"; + String PERSISTENCE_CONTEXT_TYPE_ = PERSISTENCE_CONTEXT_TYPE + '.'; + String PERSISTENCE_CONTEXT_TYPE__EXTENDED = PERSISTENCE_CONTEXT_TYPE_ + "EXTENDED"; + String PERSISTENCE_CONTEXT_TYPE__TRANSACTION = PERSISTENCE_CONTEXT_TYPE_ + "TRANSACTION"; + + String TEMPORAL_TYPE = PACKAGE_ + "TemporalType"; + String TEMPORAL_TYPE_ = TEMPORAL_TYPE + '.'; + String TEMPORAL_TYPE__DATE = TEMPORAL_TYPE_ + "DATE"; + String TEMPORAL_TYPE__TIME = TEMPORAL_TYPE_ + "TIME"; + String TEMPORAL_TYPE__TIMESTAMP = TEMPORAL_TYPE_ + "TIMESTAMP"; + + // JPA interfaces + String ENTITY_MANAGER = PACKAGE_ + "EntityManager"; + String ENTITY_MANAGER_FACTORY = PACKAGE_ + "EntityManagerFactory"; + String ENTITY_TRANSACTION = PACKAGE_ + "EntityTransaction"; + String INSTRUMENTABLE_CLASS_LOADER = PACKAGE_ + "InstrumentableClassLoader"; + String QUERY = PACKAGE_ + "Query"; + + // JPA classes + String PERSISTENCE = PACKAGE_ + "XmlPersistence"; + + // JPA exceptions + String NON_UNIQUE_RESULT_EXCEPTION = PACKAGE_ + "NonUniqueResultException"; + String OBJECT_NOT_FOUND_EXCEPTION = PACKAGE_ + "ObjectNotFoundException"; + String PERSISTENCE_EXCEPTION = PACKAGE_ + "PersistenceException"; + + + // ********** SPI ********** + + // JPA SPI package + String SPI_PACKAGE = PACKAGE_ + "spi"; + String SPI_PACKAGE_ = SPI_PACKAGE + '.'; + + // JPA SPI interfaces + String ENTITY_MANAGER_FACTORY_PROVIDER = SPI_PACKAGE_ + "EntityManagerFactoryProvider"; + String PERSISTENCE_INFO = SPI_PACKAGE_ + "PersistenceInfo"; + String PERSISTENCE_PROVIDER = SPI_PACKAGE_ + "PersistenceProvider"; + +} 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 new file mode 100644 index 0000000000..bc3bbf0d38 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/JptGenMessages.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.internal; + +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; + + 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/internal/ManyToManyRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java index 5d6c236756..dd6c07d4a8 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToManyRelation.java @@ -10,67 +10,85 @@ package org.eclipse.jpt.gen.internal; import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.utility.internal.StringTools; /** * This object is shared by the two gen tables that make up the relation. * Upon construction, 'mappedBy' will be 'null'. The first gen table to be * used to generate an entity will fill in 'mappedBy' with the appropriate - * field/property name. + * attribute (field/property) name. */ class ManyToManyRelation { - private final GenTable joinTable; + private final GenTable joinGenTable; private final ForeignKey owningForeignKey; - private final GenTable owningTable; + private final GenTable owningGenTable; private final ForeignKey nonOwningForeignKey; - private final GenTable nonOwningTable; - private String mappedBy; + private final GenTable nonOwningGenTable; + private String mappedBy; // set while generating entities - ManyToManyRelation(GenTable joinTable, ForeignKey owningForeignKey, GenTable owningTable, ForeignKey nonOwningForeignKey, GenTable nonOwningTable) { + ManyToManyRelation( + GenTable joinGenTable, + ForeignKey owningForeignKey, + GenTable owningGenTable, + ForeignKey nonOwningForeignKey, + GenTable nonOwningGenTable + ) { super(); - this.joinTable = joinTable; + this.joinGenTable = joinGenTable; this.owningForeignKey = owningForeignKey; - this.owningTable = owningTable; - owningTable.addOwnedManyToManyRelation(this); + this.owningGenTable = owningGenTable; + owningGenTable.addOwnedManyToManyRelation(this); this.nonOwningForeignKey = nonOwningForeignKey; - this.nonOwningTable = nonOwningTable; - nonOwningTable.addNonOwnedManyToManyRelation(this); + this.nonOwningGenTable = nonOwningGenTable; + nonOwningGenTable.addNonOwnedManyToManyRelation(this); } - GenTable getJoinTable() { - return this.joinTable; + GenTable getJoinGenTable() { + return this.joinGenTable; } ForeignKey getOwningForeignKey() { return this.owningForeignKey; } - GenTable getOwningTable() { - return this.owningTable; + GenTable getOwningGenTable() { + return this.owningGenTable; } ForeignKey getNonOwningForeignKey() { return this.nonOwningForeignKey; } - GenTable getNonOwningTable() { - return this.nonOwningTable; + GenTable getNonOwningGenTable() { + return this.nonOwningGenTable; } - private GenTable otherTable(GenTable table) { - return (table == this.owningTable) ? this.nonOwningTable : this.owningTable; + String getOwnedJavaAttributeName() { + return this.nonOwningGenTable.getName() + this.getCollectionAttributeNameSuffix(); } - String javaFieldNameFor(GenTable table) { - // TODO i18n? - return this.otherTable(table).javaFieldName() + "_collection"; + String getNonOwnedJavaAttributeName() { + return this.owningGenTable.getName() + this.getCollectionAttributeNameSuffix(); } + private String getCollectionAttributeNameSuffix() { + return this.getEntityConfig().getCollectionAttributeNameSuffix(); + } + + private EntityGenerator.Config getEntityConfig() { + return this.joinGenTable.getEntityConfig(); + } + + /** + * the scope clears the join table relation if there are any references + * to the join table + */ void clear() { - this.owningTable.removeOwnedManyToManyRelation(this); - this.nonOwningTable.removeNonOwnedManyToManyRelation(this); + this.owningGenTable.removeOwnedManyToManyRelation(this); + this.nonOwningGenTable.removeNonOwnedManyToManyRelation(this); } String getMappedBy() { @@ -81,24 +99,21 @@ class ManyToManyRelation { this.mappedBy = mappedBy; } - String owningEntityName() { - return this.owningTable.getEntityName(); + String getOwningEntityName() { + return this.owningGenTable.getEntityName(); } - String nonOwningEntityName() { - return this.nonOwningTable.getEntityName(); + String getNonOwningEntityName() { + return this.nonOwningGenTable.getEntityName(); } boolean joinTableNameIsDefault() { - return this.joinTable.name().equals(this.getOwningTable().name() + "_" + this.getNonOwningTable().name()); - } - - boolean joinColumnsIsDefaultFor(String javaFieldName) { - return this.owningForeignKey.isDefaultFor(javaFieldName); + return this.joinGenTable.joinTableNameIsDefault(); } - boolean inverseJoinColumnsIsDefaultFor(String javaFieldName) { - return this.nonOwningForeignKey.isDefaultFor(javaFieldName); + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.joinGenTable); } } diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java index c512f44a04..b20443506a 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/ManyToOneRelation.java @@ -10,36 +10,47 @@ package org.eclipse.jpt.gen.internal; import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.utility.internal.StringTools; +/** + * This object is held by the "base" gen table and, indirectly via a + * one-to-many relation, the "referenced" gen table. + * The "mapped by" attribute (field/property) name is set while the + * "base" table is calculating its attribute names. + */ class ManyToOneRelation { - private final GenTable baseTable; // the "many" side + private final GenTable baseGenTable; // the "many" side (e.g. Detail) private final ForeignKey foreignKey; - private final GenTable referencedTable; // the "one" side - private String mappedBy; + private final GenTable referencedGenTable; // the "one" side (e.g. Master) + private String mappedBy; // set while generating entities; used by partner one-to-many relation - ManyToOneRelation(GenTable baseTable, ForeignKey foreignKey, GenTable referencedTable) { + ManyToOneRelation( + GenTable baseGenTable, + ForeignKey foreignKey, + GenTable referencedGenTable + ) { super(); - this.baseTable = baseTable; + this.baseGenTable = baseGenTable; this.foreignKey = foreignKey; - this.referencedTable = referencedTable; - referencedTable.addOneToManyRelation(new OneToManyRelation(this)); + this.referencedGenTable = referencedGenTable; + referencedGenTable.addOneToManyRelation(new OneToManyRelation(this)); } - GenTable getBaseTable() { - return this.baseTable; + GenTable getBaseGenTable() { + return this.baseGenTable; } ForeignKey getForeignKey() { return this.foreignKey; } - GenTable getReferencedTable() { - return this.referencedTable; + GenTable getReferencedGenTable() { + return this.referencedGenTable; } - String javaFieldName() { - return this.foreignKey.getJavaFieldName(); + String getAttributeName() { + return this.foreignKey.getAttributeName(); } String getMappedBy() { @@ -50,12 +61,21 @@ class ManyToOneRelation { this.mappedBy = mappedBy; } - String baseEntityName() { - return this.baseTable.getEntityName(); + String getBaseEntityName() { + return this.baseGenTable.getEntityName(); } - String referencedEntityName() { - return this.referencedTable.getEntityName(); + String getReferencedEntityName() { + return this.referencedGenTable.getEntityName(); + } + + EntityGenerator.Config getEntityConfig() { + return this.baseGenTable.getEntityConfig(); + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.foreignKey); } } diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java index 4656d00c12..44fa78eca4 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/OneToManyRelation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 Oracle. All rights reserved. + * 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. @@ -9,9 +9,15 @@ ******************************************************************************/ package org.eclipse.jpt.gen.internal; +import org.eclipse.jpt.utility.internal.StringTools; + +/** + * This object is the inverse of the corresponding many-to-one relation. + */ class OneToManyRelation { private final ManyToOneRelation manyToOneRelation; + OneToManyRelation(ManyToOneRelation manyToOneRelation) { super(); this.manyToOneRelation = manyToOneRelation; @@ -21,17 +27,32 @@ class OneToManyRelation { return this.manyToOneRelation; } - String javaFieldName() { - // TODO i18n? - return this.manyToOneRelation.getBaseTable().javaFieldName() + "_collection"; + /** + * e.g. "FOO_collection" + */ + String getJavaAttributeName() { + return this.manyToOneRelation.getBaseGenTable().getName() + this.getCollectionAttributeNameSuffix(); } - String mappedBy() { + String getMappedBy() { return this.manyToOneRelation.getMappedBy(); } - String referencedEntityName() { - return this.manyToOneRelation.baseEntityName(); + String getReferencedEntityName() { + return this.manyToOneRelation.getBaseEntityName(); + } + + private String getCollectionAttributeNameSuffix() { + return this.getEntityConfig().getCollectionAttributeNameSuffix(); + } + + private EntityGenerator.Config getEntityConfig() { + return this.manyToOneRelation.getEntityConfig(); + } + + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.manyToOneRelation); } } diff --git a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java index 2025a0cf8d..d1f67fd8c1 100644 --- a/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.gen/src/org/eclipse/jpt/gen/internal/PackageGenerator.java @@ -9,14 +9,13 @@ ******************************************************************************/ package org.eclipse.jpt.gen.internal; -import java.util.Collection; import java.util.Iterator; + import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jpt.db.Table; -import org.eclipse.jpt.gen.internal.EntityGenerator.OverwriteConfirmer; -import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; /** * This generator will generate a package of entities for a set of tables. @@ -25,52 +24,65 @@ public class PackageGenerator { private final Config config; private final EntityGenerator.Config entityConfig; private final GenScope scope; - private final OverwriteConfirmer overwriteConfirmer; - private final IProgressMonitor monitor; // ********** public API ********** - public static void generateEntities(Config config, EntityGenerator.Config entityConfig, Collection<Table> tables, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { - if ((config == null) || (entityConfig == null) || (tables == null)) { + public static void generateEntities( + Config config, + EntityGenerator.Config entityConfig, + IProgressMonitor progressMonitor + ) { + if ((config == null) || (entityConfig == null)) { throw new NullPointerException(); } - new PackageGenerator(config, entityConfig, tables, overwriteConfirmer, monitor).generateEntities(); + SubMonitor sm = SubMonitor.convert(progressMonitor, JptGenMessages.PackageGenerator_taskName, 100); + new PackageGenerator(config, entityConfig, sm.newChild(10)).generateEntities(sm.newChild(90)); } // ********** construction/initialization ********** - private PackageGenerator(Config config, EntityGenerator.Config entityConfig, Collection<Table> tables, OverwriteConfirmer overwriteConfirmer, IProgressMonitor monitor) { + private PackageGenerator( + Config config, + EntityGenerator.Config entityConfig, + IProgressMonitor progressMonitor + ) { super(); this.config = config; this.entityConfig = entityConfig; - this.scope = new GenScope(tables, entityConfig, monitor); - this.overwriteConfirmer = overwriteConfirmer; - this.monitor = monitor; + this.scope = new GenScope(entityConfig, progressMonitor); } // ********** generation ********** - private void generateEntities() { - int size = CollectionTools.size(this.scope.entityTables()); - for (Iterator<GenTable> stream = this.scope.entityTables(); stream.hasNext(); ) { - checkCanceled(); - this.buildEntity(stream.next()); - this.monitor.worked(50/size); + private void generateEntities(IProgressMonitor progressMonitor) { + SubMonitor sm = SubMonitor.convert(progressMonitor, this.scope.entityTablesSize()); + for (Iterator<GenTable> stream = this.scope.entityGenTables(); stream.hasNext(); ) { + this.checkCanceled(sm); + this.generateEntity(stream.next(), sm.newChild(1)); } } - private void checkCanceled() { - if (this.monitor.isCanceled()) { + private void generateEntity(GenTable genTable, IProgressMonitor progressMonitor) { + EntityGenerator.generateEntity( + this.entityConfig, + this.config.getPackageFragment(), + genTable, + progressMonitor + ); + } + + private void checkCanceled(IProgressMonitor progressMonitor) { + if (progressMonitor.isCanceled()) { throw new OperationCanceledException(); - } + } } - - private void buildEntity(GenTable genTable) { - EntityGenerator.generateEntity(this.entityConfig, this.config.getPackageFragment(), genTable, overwriteConfirmer, this.monitor); + @Override + public String toString() { + return StringTools.buildToStringFor(this, this.scope); } @@ -82,6 +94,7 @@ public class PackageGenerator { public IPackageFragment getPackageFragment() { return this.packageFragment; } + public void setPackageFragment(IPackageFragment packageFragment) { this.packageFragment = packageFragment; } diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui.properties index 624bd6054d..5cc260e451 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui.properties +++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui.properties @@ -1,12 +1,12 @@ -############################################################################### +################################################################################ # 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. +# 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 -############################################################################### +################################################################################ AbstractChooserPane_browseButton=Browse... @@ -57,6 +57,8 @@ GenerateEntitiesWizardPage_tables=Tables: GenerateEntitiesWizardPage_tableColumn=Table GenerateEntitiesWizardPage_entityNameColumn=Entity Name +EntitiesGenerator_jobName=Generating Entities + GenericPlatformUiDialog_notSupportedMessageTitle=DDL Generation GenericPlatformUiDialog_notSupportedMessageText=DDL Generation is not supported by the Generic Platform. diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_mappings.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_mappings.properties index 7703f370a5..b110153f84 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_mappings.properties +++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_mappings.properties @@ -1,12 +1,12 @@ -############################################################################### +################################################################################ # 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. +# 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 -############################################################################### +################################################################################ Boolean_True=True Boolean_False=False diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_orm.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_orm.properties index c4f41ee1cd..76c53e9aa5 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_orm.properties +++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_orm.properties @@ -1,12 +1,12 @@ -############################################################################### +################################################################################ # 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. +# 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 -############################################################################### +################################################################################ AccessTypeComposite_access=Access: AccessTypeComposite_field=Field diff --git a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_persistence.properties b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_persistence.properties index a4dcb1ca0c..bd8b412043 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_persistence.properties +++ b/jpa/plugins/org.eclipse.jpt.ui/property_files/jpt_ui_persistence.properties @@ -1,12 +1,12 @@ -############################################################################### -# 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. +################################################################################ +# 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 -############################################################################### +################################################################################ Boolean_False=False Boolean_True=True diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiMessages.java index 4bc3344563..32a4787d97 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiMessages.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/JptUiMessages.java @@ -3,7 +3,7 @@ * 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 ******************************************************************************/ @@ -12,13 +12,12 @@ package org.eclipse.jpt.ui.internal; import org.eclipse.osgi.util.NLS; /** - * The resource strings used by the JPT UI classes. + * Localized messages used by Dali UI. * * @version 2.0 * @since 1.0 */ -@SuppressWarnings("nls") -public class JptUiMessages extends NLS { +public class JptUiMessages { public static String AbstractChooserPane_browseButton; public static String AddPersistentAttributeDialog_attributeLabel; @@ -137,12 +136,16 @@ public class JptUiMessages extends NLS { public static String PersistenceItemLabelProviderFactory_persistenceLabel; public static String PersistentAttributePage_mapAs; public static String PersistentTypePage_mapAs; + public static String EntitiesGenerator_jobName; + private static final String BUNDLE_NAME = "jpt_ui"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptUiMessages.class; static { - NLS.initializeMessages("jpt_ui", JptUiMessages.class); + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); } private JptUiMessages() { throw new UnsupportedOperationException(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/JptUiMappingsMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/JptUiMappingsMessages.java index 47c45aedf3..d34e55a369 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/JptUiMappingsMessages.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/JptUiMappingsMessages.java @@ -1,9 +1,9 @@ /******************************************************************************* * 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. - * + * 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 ******************************************************************************/ @@ -12,13 +12,12 @@ package org.eclipse.jpt.ui.internal.mappings; import org.eclipse.osgi.util.NLS; /** - * The localized strings used by the mapping panes. + * Localized messages used by Dali mapping panes. * * @version 2.0 * @since 1.0 */ -@SuppressWarnings("nls") -public class JptUiMappingsMessages extends NLS { +public class JptUiMappingsMessages { public static String AccessTypeCombo_default; public static String AttributeOverridesComposite_attributeOverrides; @@ -266,11 +265,14 @@ public class JptUiMappingsMessages extends NLS { public static String TemporalTypeComposite_time; public static String TemporalTypeComposite_timestamp; + private static final String BUNDLE_NAME = "jpt_ui_mappings"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptUiMappingsMessages.class; static { - NLS.initializeMessages("jpt_ui_mappings", JptUiMappingsMessages.class); + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); } private JptUiMappingsMessages() { throw new UnsupportedOperationException(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/AbstractDatabaseObjectCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/AbstractDatabaseObjectCombo.java index 01381a805a..f23d1d8a8e 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/AbstractDatabaseObjectCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/AbstractDatabaseObjectCombo.java @@ -303,20 +303,24 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs } /** - * Returns the JPA project's connection profile, which is never - * <code>null</code>. + * Returns whether the JPA project's connection profile is active. + * + * @return Whether the JPA project's connection profile is active. + */ + protected final boolean connectionProfileIsActive() { + JpaProject jpaProject = this.jpaProject(); + return (jpaProject == null) ? false : jpaProject.getDataSource().connectionProfileIsActive(); + } + + /** + * Returns the JPA project's connection profile. * * @return The connection set in the project's properties or <code>null</code> * if it could not being retrieved */ protected final ConnectionProfile connectionProfile() { - JpaProject jpaProject = jpaProject(); - - if (jpaProject != null) { - return jpaProject.getConnectionProfile(); - } - - return null; + JpaProject jpaProject = this.jpaProject(); + return (jpaProject == null) ? null : jpaProject.getConnectionProfile(); } /** @@ -326,7 +330,8 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs * connection profile was set or the */ protected final Database database() { - return connectionProfile().getDatabase(); + ConnectionProfile cp = this.connectionProfile(); + return (cp == null) ? null : cp.getDatabase(); } /** @@ -342,13 +347,12 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs */ @Override protected void disengageListeners(T subject) { - super.disengageListeners(subject); - - JpaProject jpaProject = jpaProject(); - - if (jpaProject != null) { - jpaProject.getConnectionProfile().removeConnectionListener(this.connectionListener); + ConnectionProfile cp = this.connectionProfile(); + if (cp != null) { + cp.removeConnectionListener(this.connectionListener); } + + super.disengageListeners(subject); } /* @@ -381,10 +385,9 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs protected void engageListeners(T subject) { super.engageListeners(subject); - JpaProject jpaProject = jpaProject(); - - if (jpaProject != null) { - jpaProject.getConnectionProfile().addConnectionListener(this.connectionListener); + ConnectionProfile cp = this.connectionProfile(); + if (cp != null) { + cp.addConnectionListener(this.connectionListener); } } @@ -472,10 +475,7 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs combo.removeAll(); populateDefaultValue(); - ConnectionProfile connectionProfile = connectionProfile(); - - if ((connectionProfile != null) && connectionProfile.isActive()) { - + if (this.connectionProfileIsActive()) { for (Iterator<String> iter = CollectionTools.sort(values()); iter.hasNext(); ) { combo.add(iter.next()); } @@ -675,4 +675,5 @@ public abstract class AbstractDatabaseObjectCombo<T extends JpaNode> extends Abs * choices to be added to the combo */ protected abstract Iterator<String> values(); -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/CatalogCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/CatalogCombo.java index 99144a1a9b..404e2723da 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/CatalogCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/CatalogCombo.java @@ -10,9 +10,12 @@ package org.eclipse.jpt.ui.internal.mappings.db; import java.util.Iterator; + import org.eclipse.jpt.core.JpaNode; +import org.eclipse.jpt.db.Database; import org.eclipse.jpt.ui.WidgetFactory; import org.eclipse.jpt.ui.internal.widgets.AbstractPane; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; import org.eclipse.jpt.utility.model.value.PropertyValueModel; import org.eclipse.swt.widgets.Composite; @@ -66,6 +69,8 @@ public abstract class CatalogCombo<T extends JpaNode> extends AbstractDatabaseOb @Override protected Iterator<String> values() { - return this.database().catalogNames(); + Database db = this.database(); + return (db == null) ? EmptyIterator.<String>instance() : db.catalogNames(); } + } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/ColumnCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/ColumnCombo.java index 1ce1f4e1e8..b559df52ad 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/ColumnCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/ColumnCombo.java @@ -68,40 +68,35 @@ public abstract class ColumnCombo<T extends JpaNode> extends AbstractDatabaseObj } /** - * Returns the databas tables that is used to retrieve the column names. + * Returns the database table that supplies the column names. + * Assume the subject is not null. * - * @return The table of which its columns are displayed in the combo + * @return The database table that supplies the column names. */ - protected abstract Table table(); + protected abstract Table getDBTable_(); - /* - * (non-Javadoc) + /** + * Returns the database table that supplies the column names. + * + * @return The database table that supplies the column names. */ + protected Table getDBTable() { + return (this.subject() == null) ? null : this.getDBTable_(); + + } + @Override protected void tableChanged(Table table) { super.tableChanged(table); - - if ((subject() != null) && (table() == table)) { - doPopulate(); + if (this.getDBTable() == table) { + this.doPopulate(); } } - /* - * (non-Javadoc) - */ @Override protected Iterator<String> values() { - - if (subject() == null) { - return EmptyIterator.instance(); - } - - Table table = table(); - - if (table != null) { - return table.columnNames(); - } - - return EmptyIterator.<String>instance(); + Table table = this.getDBTable(); + return (table == null) ? EmptyIterator.<String>instance() : table.columnNames(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SchemaCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SchemaCombo.java index f2f4a6fae5..10713dfc94 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SchemaCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SchemaCombo.java @@ -10,9 +10,12 @@ package org.eclipse.jpt.ui.internal.mappings.db; import java.util.Iterator; + import org.eclipse.jpt.core.JpaNode; +import org.eclipse.jpt.db.Database; import org.eclipse.jpt.ui.WidgetFactory; import org.eclipse.jpt.ui.internal.widgets.AbstractPane; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; import org.eclipse.jpt.utility.model.value.PropertyValueModel; import org.eclipse.swt.widgets.Composite; @@ -66,7 +69,8 @@ public abstract class SchemaCombo<T extends JpaNode> extends AbstractDatabaseObj @Override protected Iterator<String> values() { - return this.database().schemaNames(); + Database db = this.database(); + return (db == null) ? EmptyIterator.<String>instance() : db.schemaNames(); } } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SequenceCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SequenceCombo.java index 66b993cf34..7d4bfcaa9f 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SequenceCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/SequenceCombo.java @@ -68,17 +68,10 @@ public abstract class SequenceCombo<T extends JpaNode> extends AbstractDatabaseO protected abstract Schema schema(); - /* - * (non-Javadoc) - */ @Override protected Iterator<String> values() { Schema schema = schema(); - - if (schema != null) { - return schema.sequenceNames(); - } - - return EmptyIterator.instance(); + return (schema == null) ? EmptyIterator.<String>instance() : schema.sequenceNames(); } + } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/TableCombo.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/TableCombo.java index bb48cf9daf..6d06783e5b 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/TableCombo.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/db/TableCombo.java @@ -99,17 +99,19 @@ public abstract class TableCombo<T extends JpaNode> extends AbstractDatabaseObje */ @Override protected Iterator<String> values() { - Database database = database(); - String schemaName = schemaName(); - if ((schemaName != null) && (database != null)) { - Schema schema = database.schemaNamed(schemaName); + Database db = this.database(); + if (db == null) { + return EmptyIterator.instance(); + } - if (schema != null) { - return schema.tableNames(); - } + String schemaName = this.schemaName(); + if (schemaName == null) { + return EmptyIterator.instance(); } - return EmptyIterator.instance(); + Schema schema = db.getSchemaNamed(schemaName); + return (schema == null) ? EmptyIterator.<String>instance() : schema.tableNames(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/AbstractInheritanceComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/AbstractInheritanceComposite.java index 3a319d0ffb..b3ac8fcd41 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/AbstractInheritanceComposite.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/AbstractInheritanceComposite.java @@ -228,7 +228,7 @@ public abstract class AbstractInheritanceComposite<T extends Entity> extends Abs } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/ColumnComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/ColumnComposite.java index 5244341a7d..d24d0ab5c6 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/ColumnComposite.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/ColumnComposite.java @@ -168,7 +168,7 @@ public class ColumnComposite extends AbstractFormPane<Column> { } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/JoinColumnInRelationshipMappingStateObject.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/JoinColumnInRelationshipMappingStateObject.java index fe205a4026..b29ee8bbdd 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/JoinColumnInRelationshipMappingStateObject.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/JoinColumnInRelationshipMappingStateObject.java @@ -72,7 +72,7 @@ public class JoinColumnInRelationshipMappingStateObject extends JoinColumnStateO table = getDefaultTable(); } - return schema.tableNamed(table); + return schema.getTableNamed(table); } /* diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/SecondaryTableDialog.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/SecondaryTableDialog.java index 420d28e918..8d8bb3f666 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/SecondaryTableDialog.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/SecondaryTableDialog.java @@ -9,7 +9,6 @@ ******************************************************************************/ package org.eclipse.jpt.ui.internal.mappings.details; -import java.util.Iterator; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jpt.core.JpaProject; import org.eclipse.jpt.core.context.SecondaryTable; @@ -34,7 +33,7 @@ import org.eclipse.swt.widgets.Shell; public class SecondaryTableDialog extends Dialog { //if creating a new SecondaryTable, this will be null, - //specify the defaultSchema and defaultCatalog instead in the appropriate construtor + //specify 'defaultSchema' and 'defaultCatalog' instead in the appropriate constructor private SecondaryTable secondaryTable; private JpaProject jpaProject; private String defaultSchema; @@ -142,48 +141,46 @@ public class SecondaryTableDialog extends Dialog { } protected Database getDatabase() { - return this.getConnectionProfile().getDatabase(); + ConnectionProfile cp = this.getConnectionProfile(); + return (cp == null) ? null : cp.getDatabase(); } private ConnectionProfile getConnectionProfile() { return this.jpaProject.getConnectionProfile(); } + protected Schema getSchemaNamed(String name) { + Database db = this.getDatabase(); + return (db == null) ? null : db.getSchemaNamed(name); + } + protected Schema getDefaultTableSchema() { - if (this.secondaryTable != null) { - return getTableSchema(this.secondaryTable.getDefaultSchema()); - } - return getTableSchema(this.defaultSchema); + return this.getSchemaNamed(this.getDefaultTableSchemaName()); + } + + protected String getDefaultTableSchemaName() { + return (this.secondaryTable != null) ? this.secondaryTable.getDefaultSchema() : this.defaultSchema; } - protected Schema getTableSchema() { - if (this.secondaryTable != null) { - return getTableSchema(this.secondaryTable.getSchema()); - } - return getTableSchema(this.defaultSchema); + return this.getSchemaNamed(this.getTableSchemaName()); } - - protected Schema getTableSchema(String schemaName) { - Database database = this.getDatabase(); - if (database != null) { - return database.schemaNamed(schemaName); - } - return null; + + protected String getTableSchemaName() { + return (this.secondaryTable != null) ? this.secondaryTable.getSchema() : this.defaultSchema; } protected void populateNameCombo() { Schema schema = this.getTableSchema(); if (schema != null) { - Iterator<String> tables = schema.tableNames(); - for (Iterator<String> stream = CollectionTools.sort( tables); stream.hasNext(); ) { - this.nameCombo.add(stream.next()); + for (String name : CollectionTools.sortedSet(schema.tableNames())) { + this.nameCombo.add(name); } } - if (getSecondaryTable() != null) { - if (getSecondaryTable().getSpecifiedName() != null) { - this.nameCombo.setText(getSecondaryTable().getSpecifiedName()); + if (this.secondaryTable != null) { + if (this.secondaryTable.getSpecifiedName() != null) { + this.nameCombo.setText(this.secondaryTable.getSpecifiedName()); } } } @@ -197,16 +194,15 @@ public class SecondaryTableDialog extends Dialog { schema = this.getDefaultTableSchema(); } else if (this.schemaCombo.getText() != null) { - schema = this.getTableSchema(this.schemaCombo.getText()); + schema = this.getSchemaNamed(this.schemaCombo.getText()); } else { schema = this.getTableSchema(); } if (schema != null) { - Iterator<String> tables = schema.tableNames(); - for (Iterator<String> stream = CollectionTools.sort( tables); stream.hasNext(); ) { - this.nameCombo.add(stream.next()); + for (String name : CollectionTools.sortedSet(schema.tableNames())) { + this.nameCombo.add(name); } } @@ -214,28 +210,21 @@ public class SecondaryTableDialog extends Dialog { } protected void populateSchemaCombo() { - String defaultSchema; - if (getSecondaryTable() != null) { - defaultSchema = getSecondaryTable().getDefaultSchema(); - } - else { - defaultSchema = this.defaultSchema; - } - if (defaultSchema != null) { - this.schemaCombo.add(NLS.bind(JptUiMappingsMessages.SecondaryTableDialog_defaultSchema, defaultSchema)); + String defaultSchemaName = this.getDefaultTableSchemaName(); + if (defaultSchemaName != null) { + this.schemaCombo.add(NLS.bind(JptUiMappingsMessages.SecondaryTableDialog_defaultSchema, defaultSchemaName)); } Database database = this.getDatabase(); if (database != null) { - Iterator<String> schemata = database.schemaNames(); - for (Iterator<String> stream = CollectionTools.sort(schemata); stream.hasNext(); ) { - this.schemaCombo.add(stream.next()); + for (String name : CollectionTools.sortedSet(database.schemaNames())) { + this.schemaCombo.add(name); } } - if (getSecondaryTable() != null) { - if (getSecondaryTable().getSpecifiedSchema() != null) { - this.schemaCombo.setText(getSecondaryTable().getSpecifiedSchema()); + if (this.secondaryTable != null) { + if (this.secondaryTable.getSpecifiedSchema() != null) { + this.schemaCombo.setText(this.secondaryTable.getSpecifiedSchema()); } else { this.schemaCombo.select(0); @@ -246,30 +235,27 @@ public class SecondaryTableDialog extends Dialog { } } + protected String getDefaultTableCatalogName() { + return (this.secondaryTable != null) ? this.secondaryTable.getDefaultCatalog() : this.defaultCatalog; + } + protected void populateCatalogCombo() { - String defaultCatalog; - if (getSecondaryTable() != null) { - defaultCatalog = getSecondaryTable().getDefaultCatalog(); - } - else { - defaultCatalog = this.defaultCatalog; - } - if (defaultCatalog != null) { - this.catalogCombo.add(NLS.bind(JptUiMappingsMessages.SecondaryTableDialog_defaultCatalog, defaultCatalog)); + String defaultCatalogName = this.getDefaultTableCatalogName(); + if (defaultCatalogName != null) { + this.catalogCombo.add(NLS.bind(JptUiMappingsMessages.SecondaryTableDialog_defaultCatalog, defaultCatalogName)); } Database database = this.getDatabase(); if (database != null) { - Iterator<String> catalogs = database.catalogNames(); - for (Iterator<String> stream = CollectionTools.sort(catalogs); stream.hasNext(); ) { - this.catalogCombo.add(stream.next()); + for (String name : CollectionTools.sortedSet(database.catalogNames())) { + this.catalogCombo.add(name); } } - if (getSecondaryTable() != null) { - if (getSecondaryTable().getSpecifiedCatalog() != null) { - this.catalogCombo.setText(getSecondaryTable().getSpecifiedCatalog()); + if (this.secondaryTable != null) { + if (this.secondaryTable.getSpecifiedCatalog() != null) { + this.catalogCombo.setText(this.secondaryTable.getSpecifiedCatalog()); } else { this.catalogCombo.select(0); @@ -321,11 +307,11 @@ public class SecondaryTableDialog extends Dialog { public boolean close() { this.selectedName = this.nameCombo.getText(); this.selectedSchema = this.schemaCombo.getText(); - if (this.selectedSchema.equals("")) { + if (this.selectedSchema.equals("")) { //$NON-NLS-1$ this.selectedSchema = null; } this.selectedCatalog = this.catalogCombo.getText(); - if (this.selectedCatalog.equals("")) { + if (this.selectedCatalog.equals("")) { //$NON-NLS-1$ this.selectedCatalog = null; } this.defaultSchemaSelected = this.schemaCombo.getSelectionIndex() == 0; diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/TableGeneratorComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/TableGeneratorComposite.java index 3732245bff..d73e4ba544 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/TableGeneratorComposite.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/mappings/details/TableGeneratorComposite.java @@ -175,7 +175,7 @@ public class TableGeneratorComposite extends GeneratorComposite<TableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } @@ -225,7 +225,7 @@ public class TableGeneratorComposite extends GeneratorComposite<TableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } @@ -405,7 +405,7 @@ public class TableGeneratorComposite extends GeneratorComposite<TableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/JptUiOrmMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/JptUiOrmMessages.java index e0c9149759..51f6ae5ae5 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/JptUiOrmMessages.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/JptUiOrmMessages.java @@ -1,22 +1,22 @@ /******************************************************************************* - * 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 - *******************************************************************************/ + * 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 + ******************************************************************************/ package org.eclipse.jpt.ui.internal.orm; import org.eclipse.osgi.util.NLS; /** - * The localized messages used by the ORM widgets. + * Localized messages used by Dali ORM widgets. * * @version 2.0 * @since 1.0 */ -@SuppressWarnings("nls") public class JptUiOrmMessages { public static String AccessTypeComposite_access; @@ -77,11 +77,14 @@ public class JptUiOrmMessages { public static String PersistenceUnitMetadataSection_catalogDefault; public static String PersistenceUnitMetadataSection_schemaDefault; + private static final String BUNDLE_NAME = "jpt_ui_orm"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptUiOrmMessages.class; static { - NLS.initializeMessages("jpt_ui_orm", JptUiOrmMessages.class); + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); } private JptUiOrmMessages() { throw new UnsupportedOperationException(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/details/OrmTableGeneratorComposite.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/details/OrmTableGeneratorComposite.java index 49ea302cfa..3f0f24f1ed 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/details/OrmTableGeneratorComposite.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/orm/details/OrmTableGeneratorComposite.java @@ -103,7 +103,7 @@ public class OrmTableGeneratorComposite extends AbstractPane<OrmTableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } @@ -136,7 +136,7 @@ public class OrmTableGeneratorComposite extends AbstractPane<OrmTableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } @@ -222,7 +222,7 @@ public class OrmTableGeneratorComposite extends AbstractPane<OrmTableGenerator> } @Override - protected Table table() { + protected Table getDBTable_() { return subject().getDbTable(); } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/persistence/JptUiPersistenceMessages.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/persistence/JptUiPersistenceMessages.java index c386cfb830..bc0d3c516d 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/persistence/JptUiPersistenceMessages.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/persistence/JptUiPersistenceMessages.java @@ -1,24 +1,24 @@ /******************************************************************************* - * 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 - *******************************************************************************/ + * 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 + ******************************************************************************/ package org.eclipse.jpt.ui.internal.persistence; import org.eclipse.osgi.util.NLS; /** - * The localized messages used by the persistence editor. + * Localized messages used by Dali persistence editor. * * @version 2.0 * @since 2.0 */ -@SuppressWarnings("nls") -public class JptUiPersistenceMessages -{ +public class JptUiPersistenceMessages { + public static String Boolean_False; public static String Boolean_True; @@ -61,11 +61,14 @@ public class JptUiPersistenceMessages public static String PersistenceUnitPropertiesComposite_properties_description; public static String PersistenceUnitPropertiesComposite_valueColumn; + private static final String BUNDLE_NAME = "jpt_ui_persistence"; //$NON-NLS-1$ + private static final Class<?> BUNDLE_CLASS = JptUiPersistenceMessages.class; static { - NLS.initializeMessages("jpt_ui_persistence", JptUiPersistenceMessages.class); + NLS.initializeMessages(BUNDLE_NAME, BUNDLE_CLASS); } private JptUiPersistenceMessages() { throw new UnsupportedOperationException(); } -}
\ No newline at end of file + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator.java index 6d27bdd58c..f859879bb0 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/platform/base/EntitiesGenerator.java @@ -1,15 +1,14 @@ /******************************************************************************* -* 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 -*******************************************************************************/ + * 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 java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; @@ -25,7 +24,6 @@ import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jpt.core.JpaProject; import org.eclipse.jpt.core.context.persistence.PersistenceXml; import org.eclipse.jpt.core.internal.synch.SynchronizeClassesJob; -import org.eclipse.jpt.db.Table; import org.eclipse.jpt.gen.internal.EntityGenerator; import org.eclipse.jpt.gen.internal.PackageGenerator; import org.eclipse.jpt.ui.internal.JptUiMessages; @@ -43,99 +41,98 @@ import org.eclipse.swt.widgets.Shell; /** * EntitiesGenerator */ -public class EntitiesGenerator -{ +public class EntitiesGenerator { private JpaProject project; private IStructuredSelection selection; - // ********** constructors ********** - static public void generate( JpaProject project, IStructuredSelection selection) { - if(project == null) { - throw new NullPointerException(); - } - new EntitiesGenerator( project, selection).generate(); + // ********** construction ********** + + static public void generate(JpaProject project, IStructuredSelection selection) { + new EntitiesGenerator(project, selection).generate(); } - public EntitiesGenerator() { - super(); - } - - private EntitiesGenerator( JpaProject project, IStructuredSelection selection) { + private EntitiesGenerator(JpaProject project, IStructuredSelection selection) { super(); + if (project == null) { + throw new NullPointerException(); + } this.project = project; this.selection = selection; } - // ********** behavior ********** + // ********** 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() { GenerateEntitiesWizard wizard = new GenerateEntitiesWizard(this.project, this.selection); WizardDialog dialog = new WizardDialog(this.getCurrentShell(), wizard); dialog.create(); int returnCode = dialog.open(); - if (returnCode == Window.OK) { - WorkspaceJob genEntitiesRunnable = new GenerateEntitiesRunnable( - wizard.getPackageGeneratorConfig(), - wizard.getEntityGeneratorConfig(), - wizard.getSelectedTables(), - wizard.synchronizePersistenceXml(), - new OverwriteConfirmer(this.getCurrentShell()) - ); - - WorkspaceJob synchClassesRunnable = null; - - if (wizard.synchronizePersistenceXml()) { - // we currently only support *one* persistence.xml file per project - PersistenceXml persistenceXml = this.project.getRootContext().getPersistenceXml(); - if (persistenceXml != null) { - //TODO casting to IFile - just trying to get rid of all compiler errors for now - synchClassesRunnable = new SynchronizeClassesJob((IFile) persistenceXml.getResource()); - } - } - genEntitiesRunnable.schedule(); - if (synchClassesRunnable != null) { - synchClassesRunnable.schedule(); + if (returnCode != Window.OK) { + return; + } + + PackageGenerator.Config pConfig = wizard.getPackageGeneratorConfig(); + EntityGenerator.Config eConfig = wizard.getEntityGeneratorConfig(); + eConfig.setOverwriteConfirmer(new OverwriteConfirmer(this.getCurrentShell())); + + WorkspaceJob genEntitiesJob = new GenerateEntitiesJob(pConfig, eConfig); + + WorkspaceJob synchClassesJob = null; + + if (wizard.synchronizePersistenceXml()) { + // we currently only support *one* persistence.xml file per project + PersistenceXml persistenceXml = this.project.getRootContext().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(); + } } private Shell getCurrentShell() { return Display.getCurrent().getActiveShell(); } - // ********** runnable ********** - static class GenerateEntitiesRunnable extends WorkspaceJob { + // ********** generate entities job ********** + + static class GenerateEntitiesJob extends WorkspaceJob { private final PackageGenerator.Config packageConfig; private final EntityGenerator.Config entityConfig; - private final Collection<Table> selectedTables; - private final EntityGenerator.OverwriteConfirmer overwriteConfirmer; - GenerateEntitiesRunnable( + GenerateEntitiesJob( PackageGenerator.Config packageConfig, - EntityGenerator.Config entityConfig, - Collection<Table> selectedTables, - boolean synchronizePersistenceXml, - EntityGenerator.OverwriteConfirmer overwriteConfirmer + EntityGenerator.Config entityConfig ) { - super("Generating Entities"); + super(JptUiMessages.EntitiesGenerator_jobName); this.packageConfig = packageConfig; this.entityConfig = entityConfig; - this.selectedTables = selectedTables; - this.overwriteConfirmer = overwriteConfirmer; - setRule(packageConfig.getPackageFragment().getJavaProject().getProject()); + this.setRule(packageConfig.getPackageFragment().getJavaProject().getProject()); } @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { - PackageGenerator.generateEntities(this.packageConfig, this.entityConfig, this.selectedTables, this.overwriteConfirmer, monitor); + PackageGenerator.generateEntities(this.packageConfig, this.entityConfig, monitor); return Status.OK_STATUS; } } + // ********** overwrite confirmer ********** static class OverwriteConfirmer implements EntityGenerator.OverwriteConfirmer { @@ -159,9 +156,8 @@ public class EntitiesGenerator } private boolean promptUser(String className) { - final OverwriteConfirmerDialog dialog = new OverwriteConfirmerDialog(this.shell, className); - //get on the UI thread synchronously, need feedback before continuing + // get on the UI thread synchronously, need feedback before continuing this.shell.getDisplay().syncExec(new Runnable() { public void run() { dialog.open(); @@ -172,12 +168,15 @@ public class EntitiesGenerator } if (dialog.yes()) { return true; - } else if (dialog.yesToAll()) { + } + if (dialog.yesToAll()) { this.overwriteAll = true; return true; - } else if (dialog.no()) { + } + if (dialog.no()) { return false; - } else if (dialog.noToAll()) { + } + if (dialog.noToAll()) { this.skipAll = true; return false; } @@ -186,7 +185,8 @@ public class EntitiesGenerator } - // ********** dialog ********** + + // ********** overwrite dialog ********** static class OverwriteConfirmerDialog extends Dialog { private final String className; diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/properties/JpaProjectPropertiesPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/properties/JpaProjectPropertiesPage.java index 3dc3fb42c1..4e0d41b5d0 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/properties/JpaProjectPropertiesPage.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/properties/JpaProjectPropertiesPage.java @@ -10,6 +10,7 @@ package org.eclipse.jpt.ui.internal.properties; import java.lang.reflect.InvocationTargetException; + import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; @@ -317,27 +318,33 @@ public class JpaProjectPropertiesPage } void openNewConnectionWizard() { - String connectionName = DTPUiTools.createNewProfile(); + String connectionName = DTPUiTools.createNewConnectionProfile(); if (connectionName != null) { model.setProperty(CONNECTION, connectionName); } } - private void openConnectionProfile() { - ConnectionProfile connection = getConnectionProfile(); - connection.connect(); - model.setBooleanProperty(CONNECTION_ACTIVE, connection.isActive()); - updateConnectLink(); + void openConnectionProfile() { + ConnectionProfile cp = this.getConnectionProfile(); + if (cp != null) { + cp.connect(); + } + model.setBooleanProperty(CONNECTION_ACTIVE, (cp != null) && cp.isActive()); + this.updateConnectLink(cp); return; } - private void updateConnectLink() { - ConnectionProfile connectionProfile = getConnectionProfile(); - connectLink.setEnabled(! connectionProfile.isNull() && ! connectionProfile.isConnected()); + void updateConnectLink(ConnectionProfile cp) { + connectLink.setEnabled((cp != null) && cp.isDisconnected()); + } + + void updateConnectLink() { + this.updateConnectLink(this.getConnectionProfile()); } private ConnectionProfile getConnectionProfile() { - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(model.getStringProperty(CONNECTION)); + // we just use the connection profile to log in, so go to the db plug-in + return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(model.getStringProperty(CONNECTION)); } void performDefaults() { @@ -345,7 +352,7 @@ public class JpaProjectPropertiesPage model.setProperty(CONNECTION, connectionName); String defaultSchema = getJpaProject().getUserOverrideDefaultSchemaName(); - model.setProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA, defaultSchema != null); + model.setProperty(USER_WANTS_TO_OVERRIDE_DEFAULT_SCHEMA, Boolean.valueOf(defaultSchema != null)); model.setProperty(USER_OVERRIDE_DEFAULT_SCHEMA, defaultSchema); } } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseConnectionWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseConnectionWizardPage.java new file mode 100644 index 0000000000..880d3d908c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseConnectionWizardPage.java @@ -0,0 +1,536 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package org.eclipse.jpt.ui.internal.wizards; + +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 java.util.TreeSet; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.wizard.WizardPage; +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.Database; +import org.eclipse.jpt.db.JptDbPlugin; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.ui.internal.DTPUiTools; +import org.eclipse.jpt.ui.internal.JpaHelpContextIds; +import org.eclipse.jpt.ui.internal.JptUiMessages; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +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.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Combo; +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.Label; +import org.eclipse.swt.widgets.Link; +import org.eclipse.ui.PlatformUI; + +/** + * Most of the behavior is in DatabaseGroup.... + * + * We open the wizard page with the JPA project's connection profile and + * default schema selected (if possible), but then the selections are driven + * by the user. If the user re-selects the JPA project's connection profile, + * we will pre-select the project's default schema if possible. + */ +public class DatabaseConnectionWizardPage extends WizardPage { + + final JpaProject jpaProject; + + private final Set<Listener> listeners = Collections.synchronizedSet(new HashSet<Listener>()); + + private DatabaseGroup databaseGroup; + + static final SortedSet<String> EMPTY_SCHEMA_NAMES = new TreeSet<String>(); + + + public DatabaseConnectionWizardPage(JpaProject jpaProject) { + super("Database Settings"); //$NON-NLS-1$ + if (jpaProject == null) { + throw new NullPointerException(); + } + this.jpaProject = jpaProject; + this.setTitle(JptUiMessages.DatabaseReconnectWizardPage_databaseConnection); + this.setMessage(JptUiMessages.DatabaseReconnectWizardPage_reconnectToDatabase); + } + + public void createControl(Composite parent) { + this.setPageComplete(false); + this.setControl(this.buildTopLevelControl(parent)); + } + + private Control buildTopLevelControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout()); + this.databaseGroup = new DatabaseGroup(composite); + Dialog.applyDialogFont(parent); + PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE_CONNECTION); + return composite; + } + + public ConnectionProfile getSelectedConnectionProfile() { + return this.databaseGroup.getSelectedConnectionProfile(); + } + + public Schema getSelectedSchema() { + return this.databaseGroup.getSelectedSchema(); + } + + @Override + public void dispose() { + this.databaseGroup.dispose(); + super.dispose(); + } + + + // ********** 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) { + this.setPageComplete(schema != null); + for (Iterator<Listener> stream = this.listeners(); stream.hasNext(); ) { + stream.next().selectedSchemaChanged(schema); + } + } + + + // ********** 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); + } + + + // ********** database group ********** + + /** + * connection combo-box + * schema combo-box + * add connection link + * reconnect link + */ + class DatabaseGroup { + + // these are kept in synch with the selection + private ConnectionProfile selectedConnectionProfile; + private Schema selectedSchema; + + private final Combo connectionComboBox; + + private final Combo schemaComboBox; + + private final Link reconnectLink; + + private final ConnectionListener connectionListener; + + + // ********** construction ********** + + DatabaseGroup(Composite composite) { + super(); + + Group group = new Group(composite, SWT.NONE); + group.setLayout(new GridLayout(2, false)); // false = do not make columns equal width + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setText(JptUiMessages.DatabaseReconnectWizardPage_database); + // TODO PlatformUI.getWorkbench().getHelpSystem().setHelp(this.group, JpaHelpContextIds.XXX); + + // connection combo-box + this.buildLabel(group, 1, JptUiMessages.DatabaseReconnectWizardPage_connection); + this.connectionComboBox = this.buildComboBox(group, this.buildConnectionComboBoxSelectionListener()); + + // schema combo-box + this.buildLabel(group, 1, JptUiMessages.DatabaseReconnectWizardPage_schema); + this.schemaComboBox = this.buildComboBox(group, this.buildSchemaComboBoxSelectionListener()); + this.buildLabel(group, 2, JptUiMessages.DatabaseReconnectWizardPage_schemaInfo); + + // add connection link + this.buildLink(group, JptUiMessages.DatabaseReconnectWizardPage_addConnectionLink, this.buildAddConnectionLinkSelectionListener()); + + // reconnect link + this.reconnectLink = this.buildLink(group, JptUiMessages.DatabaseReconnectWizardPage_reconnectLink, this.buildReconnectLinkSelectionListener()); + + this.connectionListener = this.buildConnectionListener(); + + // initialize state, based on JPA project + this.selectedConnectionProfile = this.getJpaProjectConnectionProfile(); + this.selectedSchema = this.getDefaultSchema(); + + if (this.selectedSchema != null) { + DatabaseConnectionWizardPage.this.fireSchemaChanged(this.selectedSchema); + } + if (this.selectedConnectionProfile != null) { + this.selectedConnectionProfile.addConnectionListener(this.connectionListener); + DatabaseConnectionWizardPage.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 DatabaseConnectionWizardPage.this.jpaProject.getDataSource().getConnectionProfile(); + } + + /** + * this can return null; + * called at start-up and when the selected connection profile changes + */ + private Schema getDefaultSchema() { + return (this.selectedConnectionProfile == this.getJpaProjectConnectionProfile()) ? + DatabaseConnectionWizardPage.this.jpaProject.getDefaultSchema() + : + 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.reconnectLink.setEnabled(this.reconnectLinkCanBeEnabled()); + } + + private boolean reconnectLinkCanBeEnabled() { + return (this.selectedConnectionProfile != null) && this.selectedConnectionProfile.isInactive(); + } + + /** + * the schema combo-box is updated at start-up and + * when the selected connection profile changes + */ + private void updateSchemaComboBox() { + this.schemaComboBox.removeAll(); + for (String schemaName : this.buildSortedSchemaNames()) { + this.schemaComboBox.add(schemaName); + } + // the current schema *should* be in the current connection profile + if (this.selectedSchema != null) { + this.schemaComboBox.select(this.schemaComboBox.indexOf(this.selectedSchema.getName())); + } + } + + private SortedSet<String> buildSortedSchemaNames() { + if (this.selectedConnectionProfile == null) { + return EMPTY_SCHEMA_NAMES; + } + Database db = this.selectedConnectionProfile.getDatabase(); + if (db == null) { // the database is null when the connection profile is inactive + return EMPTY_SCHEMA_NAMES; + } + return CollectionTools.sortedSet(db.schemaNames()); + } + + /** + * 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 jpaProjectCP = this.getJpaProjectConnectionProfile(); + if ((jpaProjectCP != null) && jpaProjectCP.getName().equals(cpName)) { + return jpaProjectCP; + } + 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.connectionChanged(); + DatabaseConnectionWizardPage.this.fireConnectionProfileChanged(this.selectedConnectionProfile); + } + + void selectedSchemaChanged() { + Schema old = this.selectedSchema; + this.selectedSchema = this.selectedConnectionProfile.getDatabase().getSchemaNamed(this.schemaComboBox.getText()); + if (this.selectedSchema != old) { + DatabaseConnectionWizardPage.this.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(); + // everything else should be synchronized when we get the resulting open event + DatabaseConnectionWizardPage.this.fireConnectionProfileChanged(this.selectedConnectionProfile); + } + + void reconnect() { + this.selectedConnectionProfile.connect(); + // everything should be synchronized when we get the resulting open event + } + + /** + * 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) { + DatabaseConnectionWizardPage.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$ + } + }; + } + + + // ********** 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.horizontalIndent = 30; + gd.horizontalSpan = span; + label.setLayoutData(gd); + return label; + } + + /** + * build and return a combo-box + */ + private Combo buildComboBox(Composite parent, SelectionListener listener) { + Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); + combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + combo.addSelectionListener(listener); + return combo; + } + + /** + * build and return a link + */ + private Link buildLink(Composite parent, String text, SelectionListener listener) { + Link link = new Link(parent, SWT.NONE); + GridData data = new GridData(GridData.END, GridData.CENTER, false, false); + data.horizontalSpan = 2; + link.setLayoutData(data); + link.setText(text); + link.addSelectionListener(listener); + return link; + } + + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseReconnectWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseReconnectWizardPage.java deleted file mode 100644 index 1c04312695..0000000000 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/DatabaseReconnectWizardPage.java +++ /dev/null @@ -1,353 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.ui.internal.wizards; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.wizard.WizardPage; -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.Table; -import org.eclipse.jpt.db.ui.internal.DTPUiTools; -import org.eclipse.jpt.ui.internal.JpaHelpContextIds; -import org.eclipse.jpt.ui.internal.JptUiMessages; -import org.eclipse.jpt.utility.internal.CollectionTools; -import org.eclipse.jpt.utility.internal.StringTools; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.ui.PlatformUI; - -public class DatabaseReconnectWizardPage extends WizardPage -{ - private JpaProject jpaProject; - - private ConnectionProfile profile; - - private ConnectionListener connectionListener; - - private DatabaseGroup databaseGroup; - - public DatabaseReconnectWizardPage(JpaProject jpaProject) { - super("Database Settings"); //$NON-NLS-1$ - this.jpaProject = jpaProject; - setTitle(JptUiMessages.DatabaseReconnectWizardPage_databaseConnection); - setMessage(JptUiMessages.DatabaseReconnectWizardPage_reconnectToDatabase); - } - - public void createControl(Composite parent) { - this.setPageComplete(false); - Composite top = this.createTopLevelComposite(parent); - this.setControl(top); - } - - protected Composite createTopLevelComposite(Composite parent) { - Composite composite = new Composite(parent, SWT.NULL); - GridLayout layout = new GridLayout(); - composite.setLayout(layout); - this.databaseGroup = new DatabaseGroup(composite); - Dialog.applyDialogFont(parent); - // TODO Add Help - testing - PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, JpaHelpContextIds.PROPERTIES_JAVA_PERSISTENCE_CONNECTION); - return composite; - } - - private Label createLabel(Composite container, int span, String text) { - Label label = new Label(container, SWT.NONE); - label.setText(text); - GridData gd = new GridData(); - gd.horizontalIndent = 30; - gd.horizontalSpan = span; - label.setLayoutData(gd); - return label; - } - - private Combo createCombo(Composite container, boolean fillHorizontal) { - Combo combo = new Combo(container, SWT.BORDER | SWT.SINGLE); - if (fillHorizontal) { - combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - else { - combo.setLayoutData(new GridData()); - } - return combo; - } - - /** - * Initialize a grid layout with the default Dialog settings. - */ - protected GridLayout initGridLayout(GridLayout layout, boolean margins) { - layout.horizontalSpacing = this.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); - layout.verticalSpacing = this.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); - if (margins) { - layout.marginWidth = this.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); - layout.marginHeight = this.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); - } - else { - layout.marginWidth = 0; - layout.marginHeight = 0; - } - return layout; - } - - public Collection<Table> getTables() { - Schema schema = this.getDefaultSchema(); - if (schema != null && schema.getName() != null) { - return CollectionTools.collection(schema.tables()); - } - return Collections.<Table> emptyList(); - } - - private void updateGenerateEntitiesPage(Schema schema) { - if (this.getWizard() instanceof GenerateEntitiesWizard) { - GenerateEntitiesWizard generateEntitiesWizard = ((GenerateEntitiesWizard) this.getWizard()); - generateEntitiesWizard.updatePossibleTables(CollectionTools.collection(schema.tables())); - } - } - - @Override - public void dispose() { - this.removeConnectionListener(); - super.dispose(); - } - - private void removeConnectionListener() { - if (this.connectionListener != null) { - if (this.profile != null) { - this.profile.removeConnectionListener(this.connectionListener); - } - this.connectionListener = null; - } - } - - ConnectionProfile getProjectConnectionProfile() { - String profileName = this.jpaProject.getDataSource().getConnectionProfileName(); - return this.connectionProfileNamed(profileName); - } - - ConnectionProfile connectionProfileNamed(String profileName) { - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(profileName); - } - - Schema getDefaultSchema() { - return this.jpaProject.getDefaultSchema(); - } - - public String getSelectedConnectionProfileName() { - return this.databaseGroup.getConnectionProfileName(); - } - - public void clearConnectionProfileName() { - this.databaseGroup.clearConnectionProfileName(); - } - // ********** member classes ********** - private final class DatabaseGroup - { - private final Group group; - - private final Combo connectionCombo; - - private final Combo schemaCombo; - - private Link addConnectionLink; - - private Link reconnectLink; - - public DatabaseGroup(Composite composite) { - this.group = new Group(composite, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - this.group.setLayout(layout); - this.group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - this.group.setText(JptUiMessages.DatabaseReconnectWizardPage_database); - // TODO Add Help - // PlatformUI.getWorkbench().getHelpSystem().setHelp( this.group, - // IDaliHelpContextIds.XXX); - createLabel(this.group, 1, JptUiMessages.DatabaseReconnectWizardPage_connection); - this.connectionCombo = createCombo(this.group, true); - this.connectionCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - handleConnectionChange(); - } - }); - createLabel(this.group, 1, JptUiMessages.DatabaseReconnectWizardPage_schema); - this.schemaCombo = createCombo(this.group, true); - this.schemaCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - handleSchemaChange(); - } - }); - createLabel(this.group, 2, JptUiMessages.DatabaseReconnectWizardPage_schemaInfo); - this.addConnectionLink = new Link(this.group, SWT.NONE); - GridData data = new GridData(GridData.END, GridData.CENTER, false, false); - data.horizontalSpan = 2; - this.addConnectionLink.setLayoutData(data); - this.addConnectionLink.setText(JptUiMessages.DatabaseReconnectWizardPage_addConnectionLink); - this.addConnectionLink.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - openNewConnectionWizard(); - } - }); - this.reconnectLink = new Link(this.group, SWT.NONE); - data = new GridData(GridData.END, GridData.CENTER, false, false); - data.horizontalSpan = 2; - this.reconnectLink.setLayoutData(data); - this.reconnectLink.setText(JptUiMessages.DatabaseReconnectWizardPage_reconnectLink); - this.reconnectLink.setEnabled(false); - this.reconnectLink.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - openConnectionProfileNamed(getConnectionProfileName()); - } - }); - this.populateConnectionCombo(); - this.populateSchemaCombo(); - } - - private ConnectionProfile connectionProfileNamed(String profileName) { - return DatabaseReconnectWizardPage.this.connectionProfileNamed(profileName); - } - - private Iterator<String> dtpConnectionProfileNames() { - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNames(); - } - - private String getProjectConnectionProfileName() { - return jpaProject.getDataSource().getConnectionProfileName(); - } - - private void openConnectionProfileNamed(String connectionProfileName) { - DatabaseReconnectWizardPage.this.removeConnectionListener(); - DatabaseReconnectWizardPage.this.profile = this.connectionProfileNamed(connectionProfileName); - DatabaseReconnectWizardPage.this.profile.connect(); - if (DatabaseReconnectWizardPage.this.profile.isActive()) { - this.populateSchemaCombo(); - DatabaseReconnectWizardPage.this.connectionListener = this.buildConnectionListener(); - DatabaseReconnectWizardPage.this.profile.addConnectionListener(DatabaseReconnectWizardPage.this.connectionListener); - } - return; - } - - private void populateConnectionCombo() { - // clear out connection entries from previous login. - this.connectionCombo.removeAll(); - for (Iterator<String> i = CollectionTools.sort(this.dtpConnectionProfileNames()); i.hasNext();) { - this.connectionCombo.add(i.next()); - } - String connectionName = getProjectConnectionProfileName(); - if (!StringTools.stringIsEmpty(connectionName)) { - this.connectionCombo.select(connectionCombo.indexOf(connectionName)); - this.reconnectLink.setEnabled(true); - } - } - - private void handleConnectionChange() { - this.reconnectLink.setEnabled(true); - this.populateSchemaCombo(); - } - - private void handleSchemaChange() { - ConnectionProfile connectionProfile = this.connectionProfileNamed(getConnectionProfileName()); - Schema schema = connectionProfile.getDatabase().schemaNamed(this.getSchemaName()); - DatabaseReconnectWizardPage.this.updateGenerateEntitiesPage(schema); - DatabaseReconnectWizardPage.this.setPageComplete(true); - } - - private void populateSchemaCombo() { - // clear out schema entries from previous connection selection - this.schemaCombo.removeAll(); - ConnectionProfile connectionProfile = this.connectionProfileNamed(getConnectionProfileName()); - for (Iterator<String> stream = CollectionTools.sort(connectionProfile.getDatabase().schemaNames()); stream.hasNext();) { - this.schemaCombo.add(stream.next()); - } - // get default schema name from the project - Schema schema = getDefaultSchema(); - if (schema != null && schema.getName() != null) { - schema = connectionProfile.getDatabase().schemaNamed(schema.getName()); // verify - // schema - // exist - if (schema != null) { - this.schemaCombo.select(this.schemaCombo.indexOf(schema.getName())); - DatabaseReconnectWizardPage.this.updateGenerateEntitiesPage(schema); - DatabaseReconnectWizardPage.this.setPageComplete(true); - } - } - } - - private String getConnectionProfileName() { - return this.connectionCombo.getText(); - } - - private String getSchemaName() { - return this.schemaCombo.getText(); - } - - void clearConnectionProfileName() { - this.connectionCombo.setText(""); - } - - private void openNewConnectionWizard() { - String addedProfileName = DTPUiTools.createNewProfile(); - ConnectionProfile addedProfile = this.connectionProfileNamed(addedProfileName); - if (!addedProfile.isNull()) { - addedProfile.connect(); - this.populateConnectionCombo(); - this.connectionCombo.select(connectionCombo.indexOf(addedProfile.getName())); - this.handleConnectionChange(); - } - } - - private ConnectionListener buildConnectionListener() { - return new ConnectionAdapter() { - @Override - public void opened(ConnectionProfile profile) { - if (DatabaseReconnectWizardPage.this.profile.equals(profile)) { - DatabaseGroup.this.populateSchemaCombo(); - } - } - - @Override - public void aboutToClose(ConnectionProfile profile) { - if (DatabaseReconnectWizardPage.this.profile.equals(profile)) { - DatabaseReconnectWizardPage.this.removeConnectionListener(); - } - } - }; - } - } -} diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizard.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizard.java index 4b663e604a..23d51ab144 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizard.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizard.java @@ -11,13 +11,18 @@ package org.eclipse.jpt.ui.internal.wizards; import java.util.Collection; import java.util.Collections; +import java.util.Map; + import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jpt.core.EntityGeneratorDatabaseAnnotationNameBuilder; import org.eclipse.jpt.core.JpaProject; +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.internal.EntityGenerator; @@ -25,105 +30,132 @@ import org.eclipse.jpt.gen.internal.PackageGenerator; import org.eclipse.jpt.ui.internal.JptUiMessages; import org.eclipse.jpt.utility.internal.CollectionTools; +/** + * two pages: + * - a Database Connection page that allows the user to select a connection + * and a schema + * - a Generate Entities page that allows the user to select which tables in + * the selected schema are to be used and to configure Entity names + */ public class GenerateEntitiesWizard extends Wizard { - private JpaProject jpaProject; + private final JpaProject jpaProject; - private IStructuredSelection selection; + private final IStructuredSelection selection; - /** this page is only built when the project is not connected to the db */ - private DatabaseReconnectWizardPage dbSettingsPage; + private DatabaseConnectionWizardPage dbSettingsPage; private GenerateEntitiesWizardPage generateEntitiesPage; - private PackageGenerator.Config packageGeneratorConfig; + private final PackageGenerator.Config packageGeneratorConfig; - private EntityGenerator.Config entityGeneratorConfig; + private final EntityGenerator.Config entityGeneratorConfig; private boolean synchronizePersistenceXml; - - private Collection<Table> selectedTables; - public GenerateEntitiesWizard( JpaProject jpaProject, IStructuredSelection selection) { + + public GenerateEntitiesWizard(JpaProject jpaProject, IStructuredSelection selection) { super(); this.jpaProject = jpaProject; this.selection = selection; this.packageGeneratorConfig = new PackageGenerator.Config(); this.entityGeneratorConfig = new EntityGenerator.Config(); - this.setWindowTitle( JptUiMessages.GenerateEntitiesWizard_generateEntities); + this.setWindowTitle(JptUiMessages.GenerateEntitiesWizard_generateEntities); } - + @Override public void addPages() { super.addPages(); - this.dbSettingsPage = new DatabaseReconnectWizardPage( this.jpaProject); + this.dbSettingsPage = new DatabaseConnectionWizardPage(this.jpaProject); + this.dbSettingsPage.addListener(new DatabasePageListener()); this.addPage(this.dbSettingsPage); this.generateEntitiesPage = new GenerateEntitiesWizardPage(); - this.addPage( this.generateEntitiesPage); - this.generateEntitiesPage.init( this.selection); + this.addPage(this.generateEntitiesPage); + this.generateEntitiesPage.init(this.selection); } @Override + public boolean canFinish() { + return this.generateEntitiesPage.isPageComplete(); + } + + @Override public boolean performFinish() { - this.packageGeneratorConfig.setPackageFragment( this.buildPackageFragment()); - - this.entityGeneratorConfig.setConvertToCamelCase( this.generateEntitiesPage.convertToCamelCase()); - this.entityGeneratorConfig.setFieldAccessType( this.generateEntitiesPage.fieldAccessType()); - this.entityGeneratorConfig.setCollectionTypeName( this.generateEntitiesPage.getCollectionTypeName()); - this.entityGeneratorConfig.setFieldVisibility( this.generateEntitiesPage.getFieldVisibility()); - this.entityGeneratorConfig.setMethodVisibility( this.generateEntitiesPage.getMethodVisibility()); - this.entityGeneratorConfig.setGenerateGettersAndSetters( this.generateEntitiesPage.generateGettersAndSetters()); - this.entityGeneratorConfig.setGenerateDefaultConstructor( this.generateEntitiesPage.generateDefaultConstructor()); - this.entityGeneratorConfig.setSerializable( this.generateEntitiesPage.serializable()); - this.entityGeneratorConfig.setGenerateSerialVersionUID( this.generateEntitiesPage.generateSerialVersionUID()); - this.entityGeneratorConfig.setGenerateEmbeddedIdForCompoundPK( this.generateEntitiesPage.generateEmbeddedIdForCompoundPK()); - this.entityGeneratorConfig.setOverrideEntityNames( this.generateEntitiesPage.getOverrideEntityNames()); + this.packageGeneratorConfig.setPackageFragment(this.buildPackageFragment()); + + this.entityGeneratorConfig.setConvertToJavaStyleIdentifiers(this.generateEntitiesPage.convertToJavaStyleIdentifiers()); + this.entityGeneratorConfig.setFieldAccessType(this.generateEntitiesPage.fieldAccessType()); + this.entityGeneratorConfig.setCollectionTypeName(this.generateEntitiesPage.getCollectionTypeName()); + this.entityGeneratorConfig.setCollectionAttributeNameSuffix(this.generateEntitiesPage.getCollectionAttributeNameSuffix()); + this.entityGeneratorConfig.setFieldVisibility(this.generateEntitiesPage.getFieldVisibility()); + this.entityGeneratorConfig.setMethodVisibility(this.generateEntitiesPage.getMethodVisibility()); + this.entityGeneratorConfig.setGenerateGettersAndSetters(this.generateEntitiesPage.generateGettersAndSetters()); + this.entityGeneratorConfig.setGenerateDefaultConstructor(this.generateEntitiesPage.generateDefaultConstructor()); + this.entityGeneratorConfig.setSerializable(this.generateEntitiesPage.serializable()); + this.entityGeneratorConfig.setGenerateSerialVersionUID(this.generateEntitiesPage.generateSerialVersionUID()); + this.entityGeneratorConfig.setGenerateEmbeddedIdForCompoundPK(this.generateEntitiesPage.generateEmbeddedIdForCompoundPK()); + this.entityGeneratorConfig.setEmbeddedIdAttributeName(this.generateEntitiesPage.getEmbeddedIdAttributeName()); + this.entityGeneratorConfig.setPrimaryKeyMemberClassName(this.generateEntitiesPage.getPrimaryKeyMemberClassName()); + for (Map.Entry<Table, String> entry : this.generateEntitiesPage.getSelectedTables().entrySet()) { + this.entityGeneratorConfig.addTable(entry.getKey(), entry.getValue()); + } + // the name builder comes from the JPA platform + this.entityGeneratorConfig.setDatabaseAnnotationNameBuilder(this.buildDatabaseAnnotationNameBuilder()); this.synchronizePersistenceXml = this.generateEntitiesPage.synchronizePersistenceXml(); - this.selectedTables = this.generateEntitiesPage.getSelectedTables(); return true; } - + + private EntityGenerator.DatabaseAnnotationNameBuilder buildDatabaseAnnotationNameBuilder() { + return new LocalDatabaseAnnotationNameBuilder(this.jpaProject.getJpaPlatform().getEntityGeneratorDatabaseAnnotationNameBuilder()); + } + private IPackageFragment buildPackageFragment() { IPackageFragmentRoot packageFragmentRoot = this.generateEntitiesPage.getPackageFragmentRoot(); IPackageFragment packageFragment = this.generateEntitiesPage.getPackageFragment(); - if ( packageFragment == null) { - packageFragment= packageFragmentRoot.getPackageFragment( ""); //$NON-NLS-1$ + if (packageFragment == null) { + packageFragment= packageFragmentRoot.getPackageFragment(""); //$NON-NLS-1$ } - if ( packageFragment.exists()) { + if (packageFragment.exists()) { return packageFragment; } try { - return packageFragmentRoot.createPackageFragment( packageFragment.getElementName(), true, null); + return packageFragmentRoot.createPackageFragment(packageFragment.getElementName(), true, null); } - catch ( JavaModelException ex) { - throw new RuntimeException( ex); + catch (JavaModelException ex) { + throw new RuntimeException(ex); } } - + + + // ********** intra-wizard methods ********** + Collection<Table> getPossibleTables() { - if ( this.dbSettingsPage != null) { - return this.dbSettingsPage.getTables(); - } - return ( this.projectDefaultSchemaExists()) ? CollectionTools.collection( this.getDefaultSchema().tables()) : Collections.<Table>emptyList(); + return this.buildTables(this.dbSettingsPage.getSelectedSchema()); } - - ConnectionProfile getProjectConnectionProfile() { - return this.jpaProject.getConnectionProfile(); - } - + JpaProject getJpaProject(){ return this.jpaProject; } - Schema getDefaultSchema() { - return getJpaProject().getDefaultSchema(); + void selectedSchemaChanged(Schema schema) { + this.generateEntitiesPage.setPossibleTables(this.buildTables(schema)); } - + + private Collection<Table> buildTables(Schema schema) { + return (schema == null) ? + Collections.<Table>emptySet() + : + CollectionTools.collection(schema.tables()); + } + + + // ********** public methods - settings ********** + public PackageGenerator.Config getPackageGeneratorConfig() { return this.packageGeneratorConfig; } @@ -132,34 +164,54 @@ public class GenerateEntitiesWizard extends Wizard { return this.entityGeneratorConfig; } - public Collection<Table> getSelectedTables() { - return this.selectedTables; - } - public boolean synchronizePersistenceXml(){ return this.synchronizePersistenceXml; } - - @Override - public boolean canFinish() { - boolean canFinish = true; - if ( ! this.generateEntitiesPage.isPageComplete()) { - canFinish = false; - } - return canFinish; - } - - private boolean projectDefaultSchemaExists() { - return ( this.getDefaultSchema() != null); + + + // ********** name builder adapter ********** + + /** + * adapt the JPA platform-supplied builder to the builder interface + * expected by the entity generator + */ + static class LocalDatabaseAnnotationNameBuilder implements EntityGenerator.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); + } } - + + + // ********** database page listener ********** + /** - * updatePossibleTables is called when schema’s PossibleTables changed. - * The dbSettingsPage is mainly the source of changes, - * and the generateEntitiesPage needs to be kept in sync. + * listen for when the Database Connection page changes its selected schema + * so we can keep the Generate Entities page in synch */ - void updatePossibleTables( Collection<Table> possibleTables) { - this.generateEntitiesPage.updateTablesListViewer( possibleTables); + class DatabasePageListener implements DatabaseConnectionWizardPage.Listener { + public void selectedConnectionProfileChanged(ConnectionProfile connectionProfile) { + // ignore + } + public void selectedSchemaChanged(Schema schema) { + GenerateEntitiesWizard.this.selectedSchemaChanged(schema); + } } } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizardPage.java index af851c959b..45cd92c857 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizardPage.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/GenerateEntitiesWizardPage.java @@ -9,11 +9,11 @@ ******************************************************************************/ package org.eclipse.jpt.ui.internal.wizards; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; + import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.ui.wizards.NewTypeWizardPage; @@ -32,12 +32,13 @@ import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.gen.internal.EntityGenTools; import org.eclipse.jpt.gen.internal.EntityGenerator; 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.StringTools; +import org.eclipse.jpt.utility.internal.NameTools; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; @@ -53,14 +54,22 @@ import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.PlatformUI; -// TODO determine name collisions +// TODO add numerous settings to UI... +// TODO validate list of user-approved entity names: +// no duplicates (case-sensitive) +// valid Java identifiers @see NameTools.stringConsistsOfJavaIdentifierCharacters(String) +// no Java reserved words @see NameTools.JAVA_RESERVED_WORDS_SET class GenerateEntitiesWizardPage extends NewTypeWizardPage { CheckboxTableViewer tableTable; + Button synchronizeClassesCheckBox; - private boolean convertToCamelCase = true; + // TODO if this flag changes we need to re-calculate the entity names... + // (at the moment, it does not change because it is not visible to the user...) + private boolean convertToJavaStyleIdentifiers = true; private boolean fieldAccessType = true; private String collectionTypeName = Set.class.getName(); + private String collectionAttributeNameSuffix = "_collection"; //$NON-NLS-1$ private int fieldVisibility = EntityGenerator.Config.PRIVATE; private int methodVisibility = EntityGenerator.Config.PUBLIC; private boolean generateGettersAndSetters = true; @@ -68,10 +77,15 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { private boolean serializable = true; private boolean generateSerialVersionUID = true; private boolean generateEmbeddedIdForCompoundPK = true; - private boolean synchronizePersistenceXml = false; - private Map<Table, String> overrideEntityNames; + private String embeddedIdAttributeName = "pk"; //$NON-NLS-1$ + private String primaryKeyMemberClassName = "PK"; //$NON-NLS-1$ + + // key = table; value = entity name + private HashMap<Table, String> entityNames; - static final String[] TABLE_TABLE_COLUMN_PROPERTIES = { "table", "entityName" }; + private boolean synchronizePersistenceXml = false; + + static final String[] TABLE_TABLE_COLUMN_PROPERTIES = { "table", "entityName" }; //$NON-NLS-1$ //$NON-NLS-2$ private static final int TABLE_COLUMN_INDEX = 0; private static final int ENTITY_NAME_COLUMN_INDEX = 1; @@ -108,17 +122,9 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { createContainerControls(composite, nColumns); createPackageControls(composite, nColumns); - final Button synchronizeClassesCheckBox = new Button(composite, SWT.CHECK); + this.synchronizeClassesCheckBox = new Button(composite, SWT.CHECK); synchronizeClassesCheckBox.setText(JptUiMessages.GenerateEntitiesWizardPage_synchronizeClasses); - synchronizeClassesCheckBox.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - // do nothing - } - - public void widgetSelected(SelectionEvent e) { - setSynchronizePersistenceXml(synchronizeClassesCheckBox.getSelection()); - } - }); + synchronizeClassesCheckBox.addSelectionListener(this.buildSynchClassesSelectionListener()); Group tablesGroup = new Group(composite, SWT.SHADOW_ETCHED_IN); tablesGroup.setLayout(new GridLayout(2, false)); @@ -134,32 +140,49 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { createTablesSelectionControl(tablesGroup); createButtonComposite(tablesGroup); - GenerateEntitiesWizard generateEntitiesWizard = ((GenerateEntitiesWizard)this.getWizard()); - Collection<Table> possibleTables = generateEntitiesWizard.getPossibleTables(); - initTablesSelectionControl(possibleTables); + this.initTablesSelectionControl(); //set initial selection state of the synchronize classes checkbox - synchronizeClassesCheckBox.setSelection(!generateEntitiesWizard.getJpaProject().discoversAnnotatedClasses()); + synchronizeClassesCheckBox.setSelection( ! this.getGenEntitiesWizard().getJpaProject().discoversAnnotatedClasses()); setSynchronizePersistenceXml(synchronizeClassesCheckBox.getSelection()); PlatformUI.getWorkbench().getHelpSystem().setHelp(this.tableTable.getControl(), JpaHelpContextIds.DIALOG_GENERATE_ENTITIES_TABLES); setControl(composite); - this.setPageComplete( false); + this.setPageComplete(false); + } + + private GenerateEntitiesWizard getGenEntitiesWizard() { + return (GenerateEntitiesWizard) this.getWizard(); } - private void selectAllTables(){ + void selectAllTables(){ this.tableTable.setAllChecked(true); doStatusUpdate(); } - private void deselectAllTables(){ + void deselectAllTables(){ this.tableTable.setAllChecked(false); doStatusUpdate(); } - private void initTablesSelectionControl(Collection<Table> possibleTables) { - this.overrideEntityNames = new HashMap<Table, String>(possibleTables.size()); + private void initTablesSelectionControl() { + this.setPossibleTables(this.getGenEntitiesWizard().getPossibleTables()); + } + + void setPossibleTables(Collection<Table> possibleTables) { + if (this.tableTable == null) { + return; // the wizard has called this method before our widgets are built + } + this.entityNames = new HashMap<Table, String>(possibleTables.size()); + for (Table table : possibleTables) { + String tableName = table.getName(); + String entityName = (this.convertToJavaStyleIdentifiers) ? + EntityGenTools.convertToUniqueJavaStyleClassName(tableName, entityNames.values()) + : + NameTools.uniqueNameFor(tableName, entityNames.values()); + this.entityNames.put(table, entityName); + } this.tableTable.setInput(possibleTables); } @@ -197,7 +220,7 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { this.tableTable.addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { - handleTablesListSelectionChanged(event); + handleTablesListSelectionChanged(); } }); @@ -215,7 +238,6 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { } private void createButtonComposite(Group tablesGroup){ - Composite buttonComposite = new Composite(tablesGroup, SWT.NULL); GridLayout buttonLayout = new GridLayout(1, false); buttonComposite.setLayout(buttonLayout); @@ -229,31 +251,14 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { GridData gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; selectAllButton.setLayoutData(gridData); - selectAllButton.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - // do nothing - } - - public void widgetSelected(SelectionEvent e) { - selectAllTables(); - - } - }); + selectAllButton.addSelectionListener(this.buildSelectAllButtonSelectionListener()); Button deselectAllButton = new Button(buttonComposite, SWT.PUSH); deselectAllButton.setText(JptUiMessages.General_deselectAll); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; deselectAllButton.setLayoutData(gridData); - deselectAllButton.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - // do nothing - } - - public void widgetSelected(SelectionEvent e) { - deselectAllTables(); - } - }); + deselectAllButton.addSelectionListener(this.buildDeselectAllButtonSelectionListener()); } @@ -264,10 +269,9 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { void editEntityNameIfPossible(){ Object[] selected = ((IStructuredSelection) this.tableTable.getSelection()).toArray(); - if (selected.length != 1) { - return; + if (selected.length == 1) { + this.tableTable.editElement(selected[0], ENTITY_NAME_COLUMN_INDEX); } - this.tableTable.editElement(selected[0], ENTITY_NAME_COLUMN_INDEX); } private void addCellEditors() { @@ -280,9 +284,9 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { this.tableTable.setCellModifier(this.buildTableTableCellModifier()); } - void handleTablesListSelectionChanged(SelectionChangedEvent event) { + void handleTablesListSelectionChanged() { this.setPageComplete(true); - if ( ! this.hasTablesSelected()) { + if (this.noTablesAreSelected()) { this.setPageComplete(false); } } @@ -299,23 +303,20 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { return new TableTableCellModifier(); } - Collection<Table> getSelectedTables() { - ArrayList<Table> selectedTables = new ArrayList<Table>(); - for (Object selectedTable : this.tableTable.getCheckedElements()) - selectedTables.add((Table) selectedTable); + Map<Table, String> getSelectedTables() { + Object[] checkedElements = this.tableTable.getCheckedElements(); + HashMap<Table, String> selectedTables = new HashMap<Table, String>(checkedElements.length); + for (Object checkedElement : checkedElements) { + Table table = (Table) checkedElement; + selectedTables.put(table, this.entityNames.get(table)); + } return selectedTables; } - - private boolean hasTablesSelected() { - return (this.tableTable != null) ? (this.getSelectedTables().size() > 0) : false; + + private boolean noTablesAreSelected() { + return (this.tableTable == null) ? true : (this.tableTable.getCheckedElements().length == 0); } - void updateTablesListViewer(Collection<Table> possibleTables) { - if (this.tableTable != null) { - this.initTablesSelectionControl(possibleTables); - } - } - @Override protected void handleFieldChanged(String fieldName) { super.handleFieldChanged(fieldName); @@ -339,34 +340,25 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { @Override protected void updateStatus(IStatus status) { super.updateStatus(status); - if (this.isPageComplete() && ! this.hasTablesSelected()) { + if (this.isPageComplete() && this.noTablesAreSelected()) { this.setPageComplete(false); } } - String entityName(Table table) { - String overrideEntityName = this.overrideEntityNames.get(table); - return (overrideEntityName != null) ? overrideEntityName : this.defaultEntityName(table); + String getEntityName(Table table) { + return this.entityNames.get(table); } - private String defaultEntityName(Table table) { - String entityName = table.getShortJavaClassName(); - if (this.convertToCamelCase) { - entityName = StringTools.convertUnderscoresToCamelCase(entityName); - } - return entityName; - } - - void setOverrideEntityName(Table table, String name) { - if (table.getShortJavaClassName().equals(name)) { - this.overrideEntityNames.remove(table); - } else { - this.overrideEntityNames.put(table, name); - } + /** + * return whether the new entity name is different from the old entity name + */ + boolean setEntityName(Table table, String entityName) { + String old = this.entityNames.put(table, entityName); + return ! entityName.equals(old); } - boolean convertToCamelCase() { - return this.convertToCamelCase; + boolean convertToJavaStyleIdentifiers() { + return this.convertToJavaStyleIdentifiers; } boolean fieldAccessType() { @@ -377,6 +369,10 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { return this.collectionTypeName; } + String getCollectionAttributeNameSuffix() { + return this.collectionAttributeNameSuffix; + } + int getFieldVisibility() { return this.fieldVisibility; } @@ -409,22 +405,58 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { return this.synchronizePersistenceXml; } - private void setSynchronizePersistenceXml(boolean synchronizePersistenceXml){ + void setSynchronizePersistenceXml(boolean synchronizePersistenceXml){ this.synchronizePersistenceXml = synchronizePersistenceXml; } + + String getEmbeddedIdAttributeName() { + return this.embeddedIdAttributeName; + } + + String getPrimaryKeyMemberClassName() { + return this.primaryKeyMemberClassName; + } - /** - * key = table - * value = override entity name - */ - Map<Table, String> getOverrideEntityNames() { - return this.overrideEntityNames; + private SelectionListener buildSelectAllButtonSelectionListener() { + return new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + // nothing special for "default" (double-click?) + this.widgetSelected(event); + } + public void widgetSelected(SelectionEvent event) { + selectAllTables(); + } + }; + } + + private SelectionListener buildDeselectAllButtonSelectionListener() { + return new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + // nothing special for "default" (double-click?) + this.widgetSelected(event); + } + public void widgetSelected(SelectionEvent event) { + deselectAllTables(); + } + }; + } + + private SelectionListener buildSynchClassesSelectionListener() { + return new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent event) { + // nothing special for "default" (double-click?) + this.widgetSelected(event); + } + public void widgetSelected(SelectionEvent event) { + setSynchronizePersistenceXml(synchronizeClassesCheckBox.getSelection()); + } + }; } // ********** inner classes ********** - private class TableTableLabelProvider extends LabelProvider implements ITableLabelProvider { + class TableTableLabelProvider extends LabelProvider implements ITableLabelProvider { TableTableLabelProvider() { super(); @@ -448,15 +480,15 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { return ((Table) element).getName(); case ENTITY_NAME_COLUMN_INDEX: - return GenerateEntitiesWizardPage.this.entityName((Table) element); + return GenerateEntitiesWizardPage.this.getEntityName((Table) element); } - throw new IllegalArgumentException("invalid column index: " + columnIndex); + throw new IllegalArgumentException("invalid column index: " + columnIndex); //$NON-NLS-1$ } } - private class TableTableContentProvider implements IStructuredContentProvider { + static class TableTableContentProvider implements IStructuredContentProvider { TableTableContentProvider() { super(); @@ -477,7 +509,7 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { } - private class TableTableCellModifier implements ICellModifier { + class TableTableCellModifier implements ICellModifier { TableTableCellModifier() { super(); @@ -489,7 +521,7 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { public Object getValue(Object element, String property) { if (property.equals(TABLE_TABLE_COLUMN_PROPERTIES[ENTITY_NAME_COLUMN_INDEX])) { - return GenerateEntitiesWizardPage.this.entityName((Table) element); + return GenerateEntitiesWizardPage.this.getEntityName((Table) element); } return null; } @@ -501,14 +533,13 @@ class GenerateEntitiesWizardPage extends NewTypeWizardPage { if ( ! (element instanceof Table)) { return; } - - boolean unchanged = false; Table table = (Table) element; + + boolean changed = true; if (property.equals(TABLE_TABLE_COLUMN_PROPERTIES[ENTITY_NAME_COLUMN_INDEX])) { - unchanged = GenerateEntitiesWizardPage.this.entityName(table).equals(value); - GenerateEntitiesWizardPage.this.setOverrideEntityName(table, (String) value); + changed = GenerateEntitiesWizardPage.this.setEntityName(table, (String) value); } - if (! unchanged) { + if (changed) { GenerateEntitiesWizardPage.this.tableTable.update(table, new String[] { property }); } } diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/JpaFacetWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/JpaFacetWizardPage.java index 22851d2db7..70f88ba557 100644 --- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/JpaFacetWizardPage.java +++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/JpaFacetWizardPage.java @@ -15,6 +15,7 @@ import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jpt.core.internal.facet.JpaFacetDataModelProperties; import org.eclipse.jpt.db.ConnectionProfile; +import org.eclipse.jpt.db.DatabaseFinder; import org.eclipse.jpt.db.JptDbPlugin; import org.eclipse.jpt.db.ui.internal.DTPUiTools; import org.eclipse.jpt.ui.JptUiPlugin; @@ -239,27 +240,29 @@ public class JpaFacetWizardPage extends DataModelFacetInstallPage } private void openNewConnectionWizard() { - String connectionName = DTPUiTools.createNewProfile(); + String connectionName = DTPUiTools.createNewConnectionProfile(); if (connectionName != null) { model.setProperty(CONNECTION, connectionName); } } private void openConnectionProfile() { - ConnectionProfile connection = getConnectionProfile(); - connection.connect(); - model.setBooleanProperty(CONNECTION_ACTIVE, connection.isActive()); - updateConnectLink(); - return; + ConnectionProfile cp = getConnectionProfile(); + if (cp != null) { + cp.connect(); + model.setBooleanProperty(CONNECTION_ACTIVE, cp.isActive()); + updateConnectLink(); + } } private void updateConnectLink() { - ConnectionProfile connectionProfile = getConnectionProfile(); - connectLink.setEnabled(! connectionProfile.isNull() && ! connectionProfile.isConnected()); + ConnectionProfile cp = this.getConnectionProfile(); + connectLink.setEnabled((cp != null) && cp.isDisconnected()); } private ConnectionProfile getConnectionProfile() { - return JptDbPlugin.instance().getConnectionProfileRepository().connectionProfileNamed(model.getStringProperty(CONNECTION)); + // we just use the connection profile to log in, so go the the db plug-in + return JptDbPlugin.instance().getConnectionProfileFactory().buildConnectionProfile(model.getStringProperty(CONNECTION)); } } diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/BooleanHolder.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/BooleanHolder.java new file mode 100644 index 0000000000..e014e4eea1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/BooleanHolder.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * 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.utility.internal; + +import java.io.Serializable; + +/** + * Provide a container for passing a flag that can be changed by the recipient. + * @see SynchronizedBoolean + */ +public class BooleanHolder + implements Cloneable, Serializable +{ + /** Backing boolean. */ + private boolean value; + + private static final long serialVersionUID = 1L; + + + // ********** constructors ********** + + /** + * Create a boolean holder with the specified initial value. + */ + public BooleanHolder(boolean value) { + super(); + this.value = value; + } + + /** + * Create a boolean holder with an initial value of false. + */ + public BooleanHolder() { + this(false); + } + + + // ********** accessors ********** + + /** + * Return the current boolean value. + */ + public boolean getValue() { + return this.value; + } + + /** + * Return whether the current boolean value is true. + */ + public boolean isTrue() { + return this.value; + } + + /** + * Return whether the current boolean value is false. + */ + public boolean isFalse() { + return ! this.value; + } + + /** + * Return whether the current boolean value is the specified value. + */ + public boolean is(boolean v) { + return this.value == v; + } + + /** + * Set the boolean value. + */ + public void setValue(boolean value) { + this.value = value; + } + + /** + * Set the boolean value to true. + */ + public void setTrue() { + this.value = true; + } + + /** + * Set the boolean value to false. + */ + public void setFalse() { + this.value = false; + } + + + // ********** standard methods ********** + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new InternalError(); + } + } + + @Override + public boolean equals(Object o) { + if (o instanceof BooleanHolder) { + return this.value == ((BooleanHolder) o).value; + } + return false; + } + + @Override + public int hashCode() { + return this.value ? 1 : 0; + } + + @Override + public String toString() { + return '[' + String.valueOf(this.value) + ']'; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CollectionTools.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CollectionTools.java index 3b7ed63b3e..a63250198d 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CollectionTools.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/CollectionTools.java @@ -882,7 +882,11 @@ public final class CollectionTools { * java.util.Arrays#contains(char[] array, char value) */ public static boolean contains(char[] array, char value) { - for (int i = array.length; i-- > 0; ) { + return contains(array, value, array.length); + } + + private static boolean contains(char[] array, char value, int arrayLength) { + for (int i = arrayLength; i-- > 0; ) { if (array[i] == value) { return true; } @@ -896,7 +900,11 @@ public final class CollectionTools { * java.util.Arrays#contains(int[] array, int value) */ public static boolean contains(int[] array, int value) { - for (int i = array.length; i-- > 0; ) { + return contains(array, value, array.length); + } + + private static boolean contains(int[] array, int value, int arrayLength) { + for (int i = arrayLength; i-- > 0; ) { if (array[i] == value) { return true; } @@ -2785,7 +2793,7 @@ public final class CollectionTools { int[] indices = new int[array1Length]; int j = 0; for (int i = 0; i < array1Length; i++) { - if (contains(array2, array1[i])) { + if (contains(array2, array1[i], array2Length)) { indices[j++] = i; } } @@ -2825,7 +2833,7 @@ public final class CollectionTools { int[] indices = new int[array1Length]; int j = 0; for (int i = 0; i < array1Length; i++) { - if (contains(array2, array1[i])) { + if (contains(array2, array1[i], array2Length)) { indices[j++] = i; } } @@ -3426,7 +3434,7 @@ public final class CollectionTools { public Iterator<E> iterator() { if (this.iterator == null) { - throw new IllegalStateException("This method has already been called."); + throw new IllegalStateException("This method has already been called."); //$NON-NLS-1$ } Iterator<E> result = this.iterator; this.iterator = null; diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/NameTools.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/NameTools.java index fa8b5609c8..c646202c45 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/NameTools.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/NameTools.java @@ -10,9 +10,11 @@ package org.eclipse.jpt.utility.internal; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; -import java.util.Set; +import java.util.SortedSet; + import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; /** @@ -21,33 +23,10 @@ import org.eclipse.jpt.utility.internal.iterators.ArrayIterator; public final class NameTools { /** - * Given a "root" name and a set of existing names, generate a unique, - * Java-legal name that is either the "root" name or some variation on - * the "root" name (e.g. "root2", "root3",...). - * The names are case-sensitive. - */ - public static String uniqueJavaNameFor(String rootName, Iterator<String> existingNames) { - Collection<String> existingNames2 = CollectionTools.set(existingNames); - existingNames2.addAll(JAVA_RESERVED_WORDS_SET); - return uniqueNameFor(rootName, existingNames2, rootName); - } - - /** - * Given a "root" name and a set of existing names, generate a unique, - * Java-legal name that is either the "root" name or some variation on - * the "root" name (e.g. "root2", "root3",...). - * The names are case-sensitive. - */ - public static String uniqueJavaNameFor(String rootName, Collection<String> existingNames) { - Collection<String> existingNames2 = new HashSet<String>(existingNames); - existingNames2.addAll(JAVA_RESERVED_WORDS_SET); - return uniqueNameFor(rootName, existingNames2, rootName); - } - - /** * Given a "root" name and a set of existing names, generate a unique * name that is either the "root" name or some variation on the "root" - * name (e.g. "root2", "root3",...). The names are case-sensitive. + * name (e.g. "root2", "root3",...). The names are case-sensitive + * (i.e. "Root" and "root" are both allowed). */ public static String uniqueNameFor(String rootName, Iterator<String> existingNames) { return uniqueNameFor(rootName, CollectionTools.set(existingNames)); @@ -56,7 +35,8 @@ public final class NameTools { /** * Given a "root" name and a set of existing names, generate a unique * name that is either the "root" name or some variation on the "root" - * name (e.g. "root2", "root3",...). The names are case-sensitive. + * name (e.g. "root2", "root3",...). The names are case-sensitive + * (i.e. "Root" and "root" are both allowed). */ public static String uniqueNameFor(String rootName, Collection<String> existingNames) { return uniqueNameFor(rootName, existingNames, rootName); @@ -65,7 +45,8 @@ public final class NameTools { /** * Given a "root" name and a set of existing names, generate a unique * name that is either the "root" name or some variation on the "root" - * name (e.g. "root2", "root3",...). The names are NOT case-sensitive. + * name (e.g. "root2", "root3",...). The names are NOT case-sensitive + * (i.e. "Root" and "root" are NOT both allowed). */ public static String uniqueNameForIgnoreCase(String rootName, Iterator<String> existingNames) { return uniqueNameForIgnoreCase(rootName, CollectionTools.set(existingNames)); @@ -74,7 +55,8 @@ public final class NameTools { /** * Given a "root" name and a set of existing names, generate a unique * name that is either the "root" name or some variation on the "root" - * name (e.g. "root2", "root3",...). The names are NOT case-sensitive. + * name (e.g. "root2", "root3",...). The names are NOT case-sensitive + * (i.e. "Root" and "root" are NOT both allowed). */ public static String uniqueNameForIgnoreCase(String rootName, Collection<String> existingNames) { return uniqueNameFor(rootName, convertToLowerCase(existingNames), rootName.toLowerCase()); @@ -103,8 +85,8 @@ public final class NameTools { * Convert the specified collection of strings to a collection of the same * strings converted to lower case. */ - private static Collection<String> convertToLowerCase(Collection<String> strings) { - Collection<String> result = new HashBag<String>(strings.size()); + private static HashSet<String> convertToLowerCase(Collection<String> strings) { + HashSet<String> result = new HashSet<String>(strings.size()); for (String string : strings) { result.add(string.toLowerCase()); } @@ -145,6 +127,7 @@ public final class NameTools { * These words cannot be used as identifiers (i.e. names). * http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html */ + @SuppressWarnings("nls") public static final String[] JAVA_RESERVED_WORDS = new String[] { "abstract", "assert", // jdk 1.4 @@ -206,7 +189,8 @@ public final class NameTools { * These words cannot be used as identifiers (i.e. names). * http://java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html */ - public static final Set<String> JAVA_RESERVED_WORDS_SET = CollectionTools.set(JAVA_RESERVED_WORDS); + public static final SortedSet<String> JAVA_RESERVED_WORDS_SET = + Collections.unmodifiableSortedSet(CollectionTools.sortedSet(JAVA_RESERVED_WORDS)); /** * Return the set of Java programming language reserved words. @@ -218,6 +202,59 @@ public final class NameTools { } /** + * Return whether the specified string consists of Java identifier + * characters (but may be a reserved word). + */ + public static boolean stringConsistsOfJavaIdentifierCharacters(String string) { + if (string.length() == 0) { + return false; + } + return stringConsistsOfJavaIdentifierCharacters_(string.toCharArray()); + } + + /** + * Return whether the specified string consists of Java identifier + * characters (but may be a reserved word). + */ + public static boolean stringConsistsOfJavaIdentifierCharacters(char[] string) { + if (string.length == 0) { + return false; + } + return stringConsistsOfJavaIdentifierCharacters_(string); + } + + /** + * The specified string must not be empty. + */ + private static boolean stringConsistsOfJavaIdentifierCharacters_(char[] string) { + if ( ! Character.isJavaIdentifierStart(string[0])) { + return false; + } + for (int i = string.length; i-- > 1; ) { // NB: end with 1 + if ( ! Character.isJavaIdentifierPart(string[i])) { + return false; + } + } + return true; + } + + /** + * Return whether the specified string is a valid Java identifier. + */ + public static boolean stringIsLegalJavaIdentifier(String string) { + return stringConsistsOfJavaIdentifierCharacters(string) + && ! JAVA_RESERVED_WORDS_SET.contains(string); + } + + /** + * Return whether the specified string is a valid Java identifier. + */ + public static boolean stringIsLegalJavaIdentifier(char[] string) { + return stringConsistsOfJavaIdentifierCharacters(string) + && ! JAVA_RESERVED_WORDS_SET.contains(new String(string)); + } + + /** * Convert the specified string to a valid Java identifier * by substituting an underscore '_' for any invalid characters * in the string and appending an underscore '_' to the string if @@ -263,8 +300,7 @@ public final class NameTools { * to the string until it is not a Java reserved word. */ public static char[] convertToJavaIdentifier(char[] string, char c) { - int length = string.length; - if (length == 0) { + if (string.length == 0) { return string; } if (JAVA_RESERVED_WORDS_SET.contains(new String(string))) { @@ -277,7 +313,7 @@ public final class NameTools { } /** - * The specified must not be empty. + * The specified string must not be empty. * Return whether the string was modified. */ private static boolean convertToJavaIdentifier_(char[] string, char c) { @@ -299,13 +335,13 @@ public final class NameTools { private static void checkCharIsJavaIdentifierStart(char c) { if ( ! Character.isJavaIdentifierStart(c)) { - throw new IllegalArgumentException("invalid Java identifier start char: '" + c + "'"); + throw new IllegalArgumentException("invalid Java identifier start char: '" + c + '\''); //$NON-NLS-1$ } } private static void checkCharIsJavaIdentifierPart(char c) { if ( ! Character.isJavaIdentifierPart(c)) { - throw new IllegalArgumentException("invalid Java identifier part char: '" + c + "'"); + throw new IllegalArgumentException("invalid Java identifier part char: '" + c + '\''); //$NON-NLS-1$ } } diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/StringTools.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/StringTools.java index a7cc25a96c..61ee0d0e77 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/StringTools.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/StringTools.java @@ -18,15 +18,43 @@ import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; /** * Convenience methods related to the java.lang.String class. + * + * As of jdk 1.5, it's tempting to convert all of these methods to use + * java.lang.Appendable (instead of StringBuffer, StringBuilder, and Writer); + * but all the Appendable methods throw java.io.IOException (yech) and we + * [might?] get a bit better performance invoking methods on classes than + * we get on interfaces. :-) */ public final class StringTools { /** carriage return */ - public static final String CR = System.getProperty("line.separator"); + public static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ /** double quote */ public static final char QUOTE = '"'; + /** parenthesis */ + public static final char OPEN_PARENTHESIS = '('; + public static final char CLOSE_PARENTHESIS = ')'; + + /** brackets */ + public static final char OPEN_BRACKET = '['; + public static final char CLOSE_BRACKET = ']'; + + /** brackets */ + public static final char OPEN_BRACE = '{'; + public static final char CLOSE_BRACE = '}'; + + /** brackets */ + public static final char OPEN_CHEVRON = '<'; + public static final char CLOSE_CHEVRON = '>'; + + /** empty string */ + public static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + /** empty char array */ + public static final char[] EMPTY_CHAR_ARRAY = new char[0]; + // ********** padding/truncating ********** @@ -86,7 +114,7 @@ public final class StringTools { public static String pad(String string, int length, char c) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { return string; @@ -105,7 +133,7 @@ public final class StringTools { public static void padOn(String string, int length, char c, Writer writer) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { writeStringOn(string, writer); @@ -125,7 +153,7 @@ public final class StringTools { public static void padOn(String string, int length, char c, StringBuffer sb) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -145,7 +173,7 @@ public final class StringTools { public static void padOn(String string, int length, char c, StringBuilder sb) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -209,7 +237,7 @@ public final class StringTools { public static char[] pad(char[] string, int length, char c) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { return string; @@ -228,7 +256,7 @@ public final class StringTools { public static void padOn(char[] string, int length, char c, Writer writer) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { writeStringOn(string, writer); @@ -248,7 +276,7 @@ public final class StringTools { public static void padOn(char[] string, int length, char c, StringBuffer sb) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -268,7 +296,7 @@ public final class StringTools { public static void padOn(char[] string, int length, char c, StringBuilder sb) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -712,7 +740,7 @@ public final class StringTools { public static String frontPad(String string, int length, char c) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { return string; @@ -731,7 +759,7 @@ public final class StringTools { public static void frontPadOn(String string, int length, char c, Writer writer) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { writeStringOn(string, writer); @@ -751,7 +779,7 @@ public final class StringTools { public static void frontPadOn(String string, int length, char c, StringBuffer sb) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -771,7 +799,7 @@ public final class StringTools { public static void frontPadOn(String string, int length, char c, StringBuilder sb) { int stringLength = string.length(); if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -835,7 +863,7 @@ public final class StringTools { public static char[] frontPad(char[] string, int length, char c) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { return string; @@ -854,7 +882,7 @@ public final class StringTools { public static void frontPadOn(char[] string, int length, char c, Writer writer) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { writeStringOn(string, writer); @@ -874,7 +902,7 @@ public final class StringTools { public static void frontPadOn(char[] string, int length, char c, StringBuffer sb) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -894,7 +922,7 @@ public final class StringTools { public static void frontPadOn(char[] string, int length, char c, StringBuilder sb) { int stringLength = string.length; if (stringLength > length) { - throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); + throw new IllegalArgumentException("String is too long: " + stringLength + " > " + length); //$NON-NLS-1$ //$NON-NLS-2$ } if (stringLength == length) { sb.append(string); @@ -1511,6 +1539,308 @@ public final class StringTools { } + // ********** delimiting ********** + + /** + * Return whether the specified string is quoted: "\"foo\"". + */ + public static boolean stringIsQuoted(String string) { + return stringIsDelimited(string, QUOTE); + } + + /** + * Return whether the specified string is parenthetical: "(foo)". + */ + public static boolean stringIsParenthetical(String string) { + return stringIsDelimited(string, OPEN_PARENTHESIS, CLOSE_PARENTHESIS); + } + + /** + * Return whether the specified string is bracketed: "[foo]". + */ + public static boolean stringIsBracketed(String string) { + return stringIsDelimited(string, OPEN_BRACKET, CLOSE_BRACKET); + } + + /** + * Return whether the specified string is braced: "{foo}". + */ + public static boolean stringIsBraced(String string) { + return stringIsDelimited(string, OPEN_BRACE, CLOSE_BRACE); + } + + /** + * Return whether the specified string is chevroned: "<foo>". + */ + public static boolean stringIsChevroned(String string) { + return stringIsDelimited(string, OPEN_CHEVRON, CLOSE_CHEVRON); + } + + /** + * Return whether the specified string is delimited by the specified + * character. + */ + public static boolean stringIsDelimited(String string, char c) { + return stringIsDelimited(string, c, c); + } + + /** + * Return whether the specified string is delimited by the specified + * characters. + */ + public static boolean stringIsDelimited(String string, char start, char end) { + int len = string.length(); + if (len < 2) { + return false; + } + return stringIsDelimited(string.toCharArray(), start, end, len); + } + + /** + * Return whether the specified string is quoted: "\"foo\"". + */ + public static boolean stringIsQuoted(char[] string) { + return stringIsDelimited(string, QUOTE); + } + + /** + * Return whether the specified string is parenthetical: "(foo)". + */ + public static boolean stringIsParenthetical(char[] string) { + return stringIsDelimited(string, OPEN_PARENTHESIS, CLOSE_PARENTHESIS); + } + + /** + * Return whether the specified string is bracketed: "[foo]". + */ + public static boolean stringIsBracketed(char[] string) { + return stringIsDelimited(string, OPEN_BRACKET, CLOSE_BRACKET); + } + + /** + * Return whether the specified string is braced: "{foo}". + */ + public static boolean stringIsBraced(char[] string) { + return stringIsDelimited(string, OPEN_BRACE, CLOSE_BRACE); + } + + /** + * Return whether the specified string is chevroned: "<foo>". + */ + public static boolean stringIsChevroned(char[] string) { + return stringIsDelimited(string, OPEN_CHEVRON, CLOSE_CHEVRON); + } + + /** + * Return whether the specified string is delimited by the specified + * character. + */ + public static boolean stringIsDelimited(char[] string, char c) { + return stringIsDelimited(string, c, c); + } + + /** + * Return whether the specified string is delimited by the specified + * characters. + */ + public static boolean stringIsDelimited(char[] string, char start, char end) { + int len = string.length; + if (len < 2) { + return false; + } + return stringIsDelimited(string, start, end, len); + } + + private static boolean stringIsDelimited(char[] s, char start, char end, int len) { + return (s[0] == start) && (s[len - 1] == end); + } + + + // ********** unwrapping ********** + + /** + * Remove the first and last characters from the specified string. + * If the string is too short to be unwrapped, throw an + * IllegalArgumentException. + */ + public static String unwrap(String string) { + return unwrap(string, 1); + } + + /** + * Remove the first and last count characters from the specified string. + * If the string is too short to be unwrapped, throw an + * IllegalArgumentException. + */ + public static String unwrap(String string, int count) { + int len = string.length() - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + string + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return EMPTY_STRING; + } + return new String(unwrap(string.toCharArray(), len, count)); + } + + /** + * Remove the first and last characters from the specified string. + * If the string is too short to be unwrapped, throw an + * IllegalArgumentException. + */ + public static char[] unwrap(char[] string) { + return unwrap(string, 1); + } + + /** + * Remove the first and last count characters from the specified string. + * If the string is too short to be unwrapped, throw an + * IllegalArgumentException. + */ + public static char[] unwrap(char[] string, int count) { + int len = string.length - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + new String(string) + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return EMPTY_CHAR_ARRAY; + } + return unwrap(string, len, count); + } + + private static char[] unwrap(char[] string, int len, int count) { + char[] result = new char[len]; + System.arraycopy(string, count, result, 0, len); + return result; + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(String string, Writer writer) { + unwrapOn(string, 1, writer); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(String string, int count, Writer writer) { + int len = string.length() - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + string + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + writeStringOn(string, count, len, writer); + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(String string, StringBuffer sb) { + unwrapOn(string, 1, sb); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(String string, int count, StringBuffer sb) { + int len = string.length() - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + string + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + sb.append(string, count, count + len); + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(String string, StringBuilder sb) { + unwrapOn(string, 1, sb); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(String string, int count, StringBuilder sb) { + int len = string.length() - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + string + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + sb.append(string, count, count + len); + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(char[] string, Writer writer) { + unwrapOn(string, 1, writer); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(char[] string, int count, Writer writer) { + int len = string.length - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + new String(string) + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + writeStringOn(string, count, len, writer); + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(char[] string, StringBuffer sb) { + unwrapOn(string, 1, sb); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(char[] string, int count, StringBuffer sb) { + int len = string.length - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + new String(string) + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + sb.append(string, count, len); + } + + /** + * Unwrap the specified string. + */ + public static void unwrapOn(char[] string, StringBuilder sb) { + unwrapOn(string, 1, sb); + } + + /** + * Unwrap the specified string of count characters. + */ + public static void unwrapOn(char[] string, int count, StringBuilder sb) { + int len = string.length - (2 * count); + if (len < 0) { + throw new IllegalArgumentException("invalid string: \"" + new String(string) + '"'); //$NON-NLS-1$ + } + if (len == 0) { + return; + } + sb.append(string, count, len); + } + + // ********** removing characters ********** /** @@ -1547,7 +1877,7 @@ public final class StringTools { if (index == -1) { writeStringOn(string, writer); } else { - removeFirstOccurrenceOn_(string.toCharArray(), c, writer, index); + removeCharAtIndexOn(string.toCharArray(), index, writer); } } @@ -1561,7 +1891,7 @@ public final class StringTools { if (index == -1) { sb.append(string); } else { - removeFirstOccurrenceOn_(string.toCharArray(), c, sb, index); + removeCharAtIndexOn(string.toCharArray(), index, sb); } } @@ -1575,7 +1905,7 @@ public final class StringTools { if (index == -1) { sb.append(string); } else { - removeFirstOccurrenceOn_(string.toCharArray(), c, sb, index); + removeCharAtIndexOn(string.toCharArray(), index, sb); } } @@ -1616,11 +1946,11 @@ public final class StringTools { if (index == -1) { writeStringOn(string, writer); } else { - removeFirstOccurrenceOn_(string, c, writer, index); + removeCharAtIndexOn(string, index, writer); } } - private static void removeFirstOccurrenceOn_(char[] string, char c, Writer writer, int index) { + private static void removeCharAtIndexOn(char[] string, int index, Writer writer) { int last = string.length - 1; if (index == 0) { // character found at the front of string @@ -1645,11 +1975,11 @@ public final class StringTools { if (index == -1) { sb.append(string); } else { - removeFirstOccurrenceOn_(string, c, sb, index); + removeCharAtIndexOn(string, index, sb); } } - private static void removeFirstOccurrenceOn_(char[] string, char c, StringBuffer sb, int index) { + private static void removeCharAtIndexOn(char[] string, int index, StringBuffer sb) { int last = string.length - 1; if (index == 0) { // character found at the front of string @@ -1674,11 +2004,11 @@ public final class StringTools { if (index == -1) { sb.append(string); } else { - removeFirstOccurrenceOn_(string, c, sb, index); + removeCharAtIndexOn(string, index, sb); } } - private static void removeFirstOccurrenceOn_(char[] string, char c, StringBuilder sb, int index) { + private static void removeCharAtIndexOn(char[] string, int index, StringBuilder sb) { int last = string.length - 1; if (index == 0) { // character found at the front of string @@ -2488,7 +2818,7 @@ public final class StringTools { public static String buildToStringFor(Object o, Object additionalInfo) { StringBuilder sb = new StringBuilder(); buildSimpleToStringOn(o, sb); - sb.append(" ("); + sb.append(" ("); //$NON-NLS-1$ sb.append(additionalInfo); sb.append(')'); return sb.toString(); @@ -2538,10 +2868,14 @@ public final class StringTools { * only whitespace characters. */ public static boolean stringIsEmpty(String string) { - if ((string == null) || (string.length() == 0)) { + if (string == null) { + return true; + } + int len = string.length(); + if (len == 0) { return true; } - return stringIsEmpty_(string.toCharArray()); + return stringIsEmpty_(string.toCharArray(), len); } /** @@ -2549,14 +2883,18 @@ public final class StringTools { * only whitespace characters. */ public static boolean stringIsEmpty(char[] string) { - if ((string == null) || (string.length == 0)) { + if (string == null) { return true; } - return stringIsEmpty_(string); + int len = string.length; + if (len == 0) { + return true; + } + return stringIsEmpty_(string, len); } - private static boolean stringIsEmpty_(char[] s) { - for (int i = s.length; i-- > 0; ) { + private static boolean stringIsEmpty_(char[] s, int len) { + for (int i = len; i-- > 0; ) { if ( ! Character.isWhitespace(s[i])) { return false; } @@ -2565,6 +2903,22 @@ public final class StringTools { } /** + * Return whether the specified string is non-null, non-empty, and does + * not contain only whitespace characters. + */ + public static boolean stringIsNotEmpty(String string) { + return ! stringIsEmpty(string); + } + + /** + * Return whether the specified string is non-null, non-empty, and does + * not contain only whitespace characters. + */ + public static boolean stringIsNotEmpty(char[] string) { + return ! stringIsEmpty(string); + } + + /** * Return whether the specified strings are equal, ignoring case. * Check for nulls. */ @@ -2589,10 +2943,11 @@ public final class StringTools { if ((s1 == null) || (s2 == null)) { return false; // one is null but the other is not } - if (s1.length != s2.length) { + int len = s1.length; + if (len != s2.length) { return false; } - for (int i = s1.length; i-- > 0; ) { + for (int i = len; i-- > 0; ) { if ( ! charactersAreEqualIgnoreCase(s1[i], s2[i])) { return false; } @@ -2605,10 +2960,11 @@ public final class StringTools { * ignoring case. */ public static boolean stringStartsWithIgnoreCase(char[] string, char[] prefix) { - if (string.length < prefix.length) { + int prefixLength = prefix.length; + if (string.length < prefixLength) { return false; } - for (int i = prefix.length; i-- > 0; ) { + for (int i = prefixLength; i-- > 0; ) { if ( ! charactersAreEqualIgnoreCase(string[i], prefix[i])) { return false; } @@ -2635,7 +2991,44 @@ public final class StringTools { || (Character.toLowerCase(c1) == Character.toLowerCase(c2)); } - // ********** conversions ********** + /** + * Return whether the specified string is uppercase. + */ + public static boolean stringIsUppercase(String string) { + return (string.length() == 0) ? false : stringIsUppercase_(string); + } + + /** + * Return whether the specified string is uppercase. + */ + public static boolean stringIsUppercase(char[] string) { + return (string.length == 0) ? false : stringIsUppercase_(new String(string)); + } + + private static boolean stringIsUppercase_(String string) { + return string.equals(string.toUpperCase()); + } + + /** + * Return whether the specified string is lowercase. + */ + public static boolean stringIsLowercase(String string) { + return (string.length() == 0) ? false : stringIsLowercase_(string); + } + + /** + * Return whether the specified string is lowercase. + */ + public static boolean stringIsLowercase(char[] string) { + return (string.length == 0) ? false : stringIsLowercase_(new String(string)); + } + + private static boolean stringIsLowercase_(String string) { + return string.equals(string.toLowerCase()); + } + + + // ********** convert camel case to all caps ********** /** * Convert the specified "camel case" string to an "all caps" string: @@ -2977,6 +3370,9 @@ public final class StringTools { return Character.isLowerCase(next); } + + // ********** convert underscores to camel case ********** + /** * Convert the specified "underscore" string to a "camel case" string: * "LARGE_PROJECT" -> "LargeProject" @@ -3181,6 +3577,206 @@ public final class StringTools { } + // ********** convert to Java string literal ********** + + public static final String EMPTY_JAVA_STRING_LITERAL = "\"\""; //$NON-NLS-1$ + public static final char[] EMPTY_JAVA_STRING_LITERAL_CHAR_ARRAY = EMPTY_JAVA_STRING_LITERAL.toCharArray(); + + public static String convertToJavaStringLiteral(String string) { + int len = string.length(); + if (len == 0) { + return EMPTY_JAVA_STRING_LITERAL; + } + StringBuilder sb = new StringBuilder(len + 5); + convertToJavaStringLiteralOn_(string.toCharArray(), sb, len); + return sb.toString(); + } + + public static char[] convertToJavaStringLiteral(char[] string) { + int len = string.length; + if (len == 0) { + return EMPTY_JAVA_STRING_LITERAL_CHAR_ARRAY; + } + StringBuilder sb = new StringBuilder(len + 5); + convertToJavaStringLiteralOn_(string, sb, len); + len = sb.length(); + char[] result = new char[len]; + sb.getChars(0, len, result, 0); + return result; + } + + public static void convertToJavaStringLiteralOn(String string, StringBuffer sb) { + int len = string.length(); + if (len == 0) { + sb.append(EMPTY_JAVA_STRING_LITERAL); + } else { + convertToJavaStringLiteralOn_(string.toCharArray(), sb, len); + } + } + + public static void convertToJavaStringLiteralOn(char[] string, StringBuffer sb) { + int len = string.length; + if (len == 0) { + sb.append(EMPTY_JAVA_STRING_LITERAL); + } else { + convertToJavaStringLiteralOn_(string, sb, len); + } + } + + /* + * no length checks + */ + private static void convertToJavaStringLiteralOn_(char[] string, StringBuffer sb, int len) { + sb.ensureCapacity(sb.length() + len + 5); + sb.append(QUOTE); + for (char c : string) { + switch (c) { + case '\b': // backspace + sb.append("\\b"); //$NON-NLS-1$ + break; + case '\t': // horizontal tab + sb.append("\\t"); //$NON-NLS-1$ + break; + case '\n': // line-feed LF + sb.append("\\n"); //$NON-NLS-1$ + break; + case '\f': // form-feed FF + sb.append("\\f"); //$NON-NLS-1$ + break; + case '\r': // carriage-return CR + sb.append("\\r"); //$NON-NLS-1$ + break; + case '"': // double-quote + sb.append("\\\""); //$NON-NLS-1$ + break; +// case '\'': // single-quote +// sb.append("\\'"); //$NON-NLS-1$ +// break; + case '\\': // backslash + sb.append("\\\\"); //$NON-NLS-1$ + break; + default: + sb.append(c); + break; + } + } + sb.append(QUOTE); + } + + public static void convertToJavaStringLiteralOn(String string, StringBuilder sb) { + int len = string.length(); + if (len == 0) { + sb.append(EMPTY_JAVA_STRING_LITERAL); + } else { + convertToJavaStringLiteralOn_(string.toCharArray(), sb, len); + } + } + + public static void convertToJavaStringLiteralOn(char[] string, StringBuilder sb) { + int len = string.length; + if (len == 0) { + sb.append(EMPTY_JAVA_STRING_LITERAL); + } else { + convertToJavaStringLiteralOn_(string, sb, len); + } + } + + /* + * no length checks + */ + private static void convertToJavaStringLiteralOn_(char[] string, StringBuilder sb, int len) { + sb.ensureCapacity(sb.length() + len + 5); + sb.append(QUOTE); + for (char c : string) { + switch (c) { + case '\b': // backspace + sb.append("\\b"); //$NON-NLS-1$ + break; + case '\t': // horizontal tab + sb.append("\\t"); //$NON-NLS-1$ + break; + case '\n': // line-feed LF + sb.append("\\n"); //$NON-NLS-1$ + break; + case '\f': // form-feed FF + sb.append("\\f"); //$NON-NLS-1$ + break; + case '\r': // carriage-return CR + sb.append("\\r"); //$NON-NLS-1$ + break; + case '"': // double-quote + sb.append("\\\""); //$NON-NLS-1$ + break; +// case '\'': // single-quote +// sb.append("\\'"); //$NON-NLS-1$ +// break; + case '\\': // backslash + sb.append("\\\\"); //$NON-NLS-1$ + break; + default: + sb.append(c); + break; + } + } + sb.append(QUOTE); + } + + public static void convertToJavaStringLiteralOn(String string, Writer writer) { + if (string.length() == 0) { + writeStringOn(EMPTY_JAVA_STRING_LITERAL, writer); + } else { + convertToJavaStringLiteralOn_(string.toCharArray(), writer); + } + } + + public static void convertToJavaStringLiteralOn(char[] string, Writer writer) { + if (string.length == 0) { + writeStringOn(EMPTY_JAVA_STRING_LITERAL, writer); + } else { + convertToJavaStringLiteralOn_(string, writer); + } + } + + /* + * no length checks + */ + private static void convertToJavaStringLiteralOn_(char[] string, Writer writer) { + writeCharOn(QUOTE, writer); + for (char c : string) { + switch (c) { + case '\b': // backspace + writeStringOn("\\b", writer); //$NON-NLS-1$ + break; + case '\t': // horizontal tab + writeStringOn("\\t", writer); //$NON-NLS-1$ + break; + case '\n': // line-feed LF + writeStringOn("\\n", writer); //$NON-NLS-1$ + break; + case '\f': // form-feed FF + writeStringOn("\\f", writer); //$NON-NLS-1$ + break; + case '\r': // carriage-return CR + writeStringOn("\\r", writer); //$NON-NLS-1$ + break; + case '"': // double-quote + writeStringOn("\\\"", writer); //$NON-NLS-1$ + break; +// case '\'': // single-quote +// writeStringOn("\\'", writer); //$NON-NLS-1$ +// break; + case '\\': // backslash + writeStringOn("\\\\", writer); //$NON-NLS-1$ + break; + default: + writeCharOn(c, writer); + break; + } + } + writeCharOn(QUOTE, writer); + } + + // ********** convenience ********** public static char[] convertToCharArray(StringBuffer sb) { @@ -3213,6 +3809,14 @@ public final class StringTools { } } + private static void writeStringOn(String string, int off, int len, Writer writer) { + try { + writer.write(string, off, len); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + private static void writeStringOn(String string, Writer writer) { try { writer.write(string); diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/SynchronizedBoolean.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/SynchronizedBoolean.java index 92b6bc1f96..3474a6505e 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/SynchronizedBoolean.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/SynchronizedBoolean.java @@ -17,6 +17,7 @@ import org.eclipse.jpt.utility.Command; * This class provides synchronized access to a boolean value. * It also provides protocol for suspending a thread until the * boolean value is set to true or false, with optional time-outs. + * @see BooleanHolder */ public class SynchronizedBoolean implements Cloneable, Serializable @@ -97,6 +98,15 @@ public class SynchronizedBoolean } /** + * Return whether the current boolean value is the specified value. + */ + public boolean is(boolean v) { + synchronized (this.mutex) { + return this.value == v; + } + } + + /** * Set the boolean value. If the value changes, all waiting * threads are notified. */ diff --git a/jpa/tests/org.eclipse.jpt.core.tests.extension.resource/src/org/eclipse/jpt/core/tests/extension/resource/TestJpaPlatform.java b/jpa/tests/org.eclipse.jpt.core.tests.extension.resource/src/org/eclipse/jpt/core/tests/extension/resource/TestJpaPlatform.java index 9aa0335ff1..40b1b77f49 100644 --- a/jpa/tests/org.eclipse.jpt.core.tests.extension.resource/src/org/eclipse/jpt/core/tests/extension/resource/TestJpaPlatform.java +++ b/jpa/tests/org.eclipse.jpt.core.tests.extension.resource/src/org/eclipse/jpt/core/tests/extension/resource/TestJpaPlatform.java @@ -9,7 +9,8 @@ ******************************************************************************/ package org.eclipse.jpt.core.tests.extension.resource; -import java.util.Collection; +import java.util.List; + import org.eclipse.jpt.core.JpaAnnotationProvider; import org.eclipse.jpt.core.JpaFactory; import org.eclipse.jpt.core.context.java.JavaAttributeMappingProvider; @@ -36,13 +37,13 @@ public class TestJpaPlatform extends GenericJpaPlatform } @Override - protected void addJavaTypeMappingProvidersTo(Collection<JavaTypeMappingProvider> providers) { + protected void addJavaTypeMappingProvidersTo(List<JavaTypeMappingProvider> providers) { super.addJavaTypeMappingProvidersTo(providers); providers.add(JavaTestTypeMappingProvider.instance()); } @Override - protected void addJavaAttributeMappingProvidersTo(Collection<JavaAttributeMappingProvider> providers) { + protected void addJavaAttributeMappingProvidersTo(List<JavaAttributeMappingProvider> providers) { super.addJavaAttributeMappingProvidersTo(providers); providers.add(JavaTestAttributeMappingProvider.instance()); } diff --git a/jpa/tests/org.eclipse.jpt.core.tests/build.properties b/jpa/tests/org.eclipse.jpt.core.tests/build.properties index 9bf11f791e..96de1ee6d2 100644 --- a/jpa/tests/org.eclipse.jpt.core.tests/build.properties +++ b/jpa/tests/org.eclipse.jpt.core.tests/build.properties @@ -1,13 +1,12 @@ -############################################################################### -# Copyright (c) 2006, 2007 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 +################################################################################ +# 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 -############################################################################### +# Oracle - initial API and implementation +################################################################################ javacSource = 1.5 javacTarget = 1.5 bin.includes = .,\ diff --git a/jpa/tests/org.eclipse.jpt.db.tests/META-INF/MANIFEST.MF b/jpa/tests/org.eclipse.jpt.db.tests/META-INF/MANIFEST.MF index 23cadfc899..05d1eae9d8 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/META-INF/MANIFEST.MF +++ b/jpa/tests/org.eclipse.jpt.db.tests/META-INF/MANIFEST.MF @@ -13,6 +13,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.junit;bundle-version="[3.8.2,4.0.0)", org.eclipse.datatools.connectivity;bundle-version="[1.1.0,1.2.0)", org.eclipse.datatools.connectivity.db.generic;bundle-version="[1.0.0,1.2.0)", + org.eclipse.datatools.connectivity.sqm.core;bundle-version="1.0.1", + org.eclipse.datatools.modelbase.sql;bundle-version="1.0.0", org.eclipse.jpt.utility;bundle-version="[1.2.0,2.0.0)", org.eclipse.jpt.db;bundle-version="[1.1.1,2.0.0)" Export-Package: org.eclipse.jpt.db.tests.internal;x-internal:=true, diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/derby.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/derby.properties new file mode 100644 index 0000000000..a02643af95 --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/derby.properties @@ -0,0 +1,24 @@ +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional for Derby +userID = +password = + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/derby/lib/derby.jar +jars = C:/derby/lib/derby.jar + +# the JDBC URL is required for Derby +# url = jdbc:derby:C:/derby/data/testdb;create=true +url = jdbc:derby:C:/derby/data/testdb;create=true diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/derby101.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/derby101.properties deleted file mode 100644 index 1d97add8dd..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/derby101.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver class name - org.apache.derby.jdbc.EmbeddedDriver -# -profileName = derby101 -profileDescription = Derby Embedded JDBC Profile for Testing -# set user name -userName = -userPassword = -# set path to Derby driver here (example: databasedriverJarList = c:/derbydb/lib/derby.jar ) -databasedriverJarList = -databaseName = testdb -# set database URL here (example: databaseUrl = jdbc:derby:c:/derbydb/testdb;create=true ) -databaseUrl = diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/mysql.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/mysql.properties new file mode 100644 index 0000000000..378b02cd4d --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/mysql.properties @@ -0,0 +1,26 @@ +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = +password = + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/mysql/mysql-connector-java-5.0.6-bin.jar +jars = C:/mysql/mysql-connector-java-5.0.6-bin.jar + +# the JDBC URL is optional for MySQL +# url = jdbc:mysql://localhost:3306 + +# the database is optional +# database = testdb diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/mysql41.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/mysql41.properties deleted file mode 100644 index 4ac94784bb..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/mysql41.properties +++ /dev/null @@ -1,22 +0,0 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# -# Driver class (jconn3.jar) - com.mysql.jdbc.Driver -# -profileName = mysq41 -profileDescription = MySql 4.1.16 JDBC Profile for Testing -# set user name -userName = -userPassword = -# set path to Derby driver here (example: databasedriverJarList = C:/jlib/mysql-connector-java-3.1.7-bin.jar ) -databasedriverJarList = -databaseName = testdb -# set database URL here (example: databaseUrl = jdbc:sybase:Tds:localhost:5000/testdb ) -databaseUrl = diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10g.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10g.properties index 603e56d7db..9c66852cd3 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10g.properties +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10g.properties @@ -1,20 +1,27 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - jar list separate by comma (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver: oracle.jdbc.OracleDriver -# -profileName = Oracle10g_10_1_0_4 -profileDescription = Oracle10g (10.1.0.4) Thin JDBC Profile for Testing -userName = -userPassword = -# set path to Oracle driver here (example: databasedriverJarList = c:/oracle/jdbc/lib/ojdbc14.jar ) -databasedriverJarList = -databaseName = -# set database URL here (example: databaseUrl = jdbc:oracle:thin:@localhost:1521:testdb ) -databaseUrl = +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = scott +password = tiger + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/oracle/jdbc/lib/ojdbc5.jar +jars = C:/oracle/jdbc/lib/ojdbc5.jar + +# the JDBC URL is required +# url = jdbc:oracle:thin:@localhost:1521:testdb +url = jdbc:oracle:thin:@localhost:1521:orcl + +# the database is optional +database = orcl diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10gXE.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10gXE.properties index 8d72946e2a..8f76631645 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10gXE.properties +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle10gXE.properties @@ -1,20 +1,27 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - jar list separate by comma (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver: oracle.jdbc.OracleDriver -# -profileName = oracleXE10g -profileDescription = Oracle10g XE Release 2 (10.2) Thin JDBC Profile for Testing -userName = scott -userPassword = tiger -# set path to Oracle driver here (example: databasedriverJarList = c:/oracle/jdbc/lib/ojdbc14.jar ) -databasedriverJarList = -databaseName = XE -# set database URL here (example: databaseUrl = jdbc:oracle:thin:@localhost:1521:XE ) -databaseUrl = +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = scott +password = tiger + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/oracle/jdbc/lib/ojdbc14.jar +jars = + +# the JDBC URL is required +# url = jdbc:oracle:thin:@localhost:1521:XE +url = + +# the database is optional +database = XE diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle9i.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle9i.properties index 8357e15c58..669d5d8775 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/oracle9i.properties +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/oracle9i.properties @@ -1,20 +1,27 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - jar list separate by comma (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver: oracle.jdbc.OracleDriver -# -profileName = oracle9i -profileDescription = Oracle Thin JDBC Profile for Testing -userName = -userPassword = -# set path to Oracle driver here (example: databasedriverJarList = c:/oracle/jdbc/lib/ojdbc14.jar ) -databasedriverJarList = -databaseName = testdb -# set database URL here (example: databaseUrl = jdbc:oracle:thin:@server:1521:testdb ) -databaseUrl = +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = scott +password = tiger + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/oracle/jdbc/lib/ojdbc14.jar +jars = + +# the JDBC URL is required +# url = jdbc:oracle:thin:@localhost:1521:testdb +url = + +# the database is optional +database = testdb diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql.properties new file mode 100644 index 0000000000..eed8b7398b --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql.properties @@ -0,0 +1,23 @@ +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = +password = + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/postgresql/jdbc/postgresql-8.2-506.jdbc3.jar +jars = C:/postgresql/jdbc/postgresql-8.2-506.jdbc3.jar + +# the JDBC URL is optional for PostgreSQL +# url = jdbc:postgresql diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql824.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql824.properties deleted file mode 100644 index f529359523..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/postgresql824.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver class (postgresql-8.2-505.jdbc2.jar) - org.postgresql.Driver -# -profileName = postgresql -profileDescription = PostgreSQL 8.2.4 JDBC Profile for Testing -# set user name -userName = -userPassword = -# set path to Derby driver here (example: databasedriverJarList = c:/jlib/postgresql-8.2-505.jdbc2.jar) -databasedriverJarList = -databaseName = postgres -# set database URL here (example: databaseUrl = jdbc:postgresql:postgres ) -databaseUrl = jdbc:postgresql:postgres diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver.properties new file mode 100644 index 0000000000..0ec008a451 --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver.properties @@ -0,0 +1,27 @@ +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = +password = + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/sqlserver/lib/sqljdbc.jar +jars = + +# the JDBC URL is required +# url = jdbc:sqlserver://localhost:1433;databaseName=testdb +url = + +# the database is optional +database = testdb diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver2005.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver2005.properties deleted file mode 100644 index 8451351e83..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/sqlserver2005.properties +++ /dev/null @@ -1,30 +0,0 @@ -############################################################################### -# Copyright (c) 2007 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 -############################################################################### -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# -profileName = sqlserver2005 -profileDescription = MS SQL Server 2005 JDBC Profile for Testing -# set user name -userName = -userPassword = -# set path to Derby driver here (example: databasedriverJarList = c:/sqlserver/lib/sqljdbc.jar ) -databasedriverJarList = -databaseName = testdb -# set database URL here (example: databaseUrl = jdbc:sqlserver://localhost:1433;databaseName=testdb ) -databaseUrl = diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/sybase.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/sybase.properties new file mode 100644 index 0000000000..908f5e730c --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/config/sybase.properties @@ -0,0 +1,27 @@ +################################################################################ +# 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 +################################################################################ + +# Configure the workspace- and database server-specific settings here. + +# user and password are optional, depending on the platform +userID = +password = + +# the JDBC driver JAR(s) must be specified; +# if there are multiple JARs, separate the names with commas +# jars = C:/sybase/lib/jconn3.jar +jars = + +# the JDBC URL is required +# url = jdbc:sybase:Tds:localhost:5000/testdb +url = + +# the database is optional +database = testdb diff --git a/jpa/tests/org.eclipse.jpt.db.tests/config/sybase12.properties b/jpa/tests/org.eclipse.jpt.db.tests/config/sybase12.properties deleted file mode 100644 index 34aab2556b..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/config/sybase12.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Platform Property names & Default -# -# profileName - jpatest -# profileDescription - JDBC Profile for JPA Testing -# userName - jpatest -# userPassword - (empty) -# databasedriverJarList - (mandatory) -# databaseName - testdb -# databaseUrl - (mandatory) -# Driver class (jconn3.jar) - com.sybase.jdbc3.jdbc.SybDriver -# -profileName = jconnect6 -profileDescription = Sybase 12.x jConnect JDBC Profile for Testing -# set user name -userName = -userPassword = -# set path to Derby driver here (example: databasedriverJarList = c:/sybase/lib/jconn3.jar ) -databasedriverJarList = -databaseName = testdb -# set database URL here (example: databaseUrl = jdbc:sybase:Tds:localhost:5000/testdb ) -databaseUrl = diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTests.java index ecb2b84188..f8c0ca49cc 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 Oracle. All rights reserved. + * 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. @@ -13,17 +13,12 @@ import org.eclipse.jpt.db.tests.internal.platforms.AllPlatformTests; import junit.framework.Test; import junit.framework.TestSuite; -import junit.swingui.TestRunner; /** - * JptDbTests + * JPT DB Tests */ public class JptDbTests { - public static void main( String[] args) { - TestRunner.main( new String[] { "-c", JptDbTests.class.getName()}); - } - public static Test suite() { TestSuite suite = new TestSuite(JptDbTests.class.getPackage().getName()); @@ -36,4 +31,5 @@ public class JptDbTests { super(); throw new UnsupportedOperationException(); } + } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTestsPlugin.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTestsPlugin.java index a5fe382da0..11c2a7e84a 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTestsPlugin.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/JptDbTestsPlugin.java @@ -1,9 +1,9 @@ /******************************************************************************* * 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. - * + * 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 ******************************************************************************/ diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/AllPlatformTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/AllPlatformTests.java index c11b296e3f..0b5de9abea 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/AllPlatformTests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/AllPlatformTests.java @@ -21,14 +21,14 @@ public class AllPlatformTests { TestSuite suite = new TestSuite(AllPlatformTests.class.getPackage().getName()); // TODO - Uncomment the platform to test. -// suite.addTestSuite(Derby101Tests.class); -// suite.addTestSuite(Oracle9iTests.class); +// suite.addTestSuite(DerbyTests.class); +// suite.addTestSuite(MySQLTests.class); // suite.addTestSuite(Oracle10gTests.class); // suite.addTestSuite(Oracle10gXETests.class); -// suite.addTestSuite(SQLServer2005Tests.class); -// suite.addTestSuite(MySQL41Tests.class); -// suite.addTestSuite(PostgreSQL824Tests.class); -// suite.addTestSuite(Sybase12Tests.class); +// suite.addTestSuite(Oracle9iTests.class); +// suite.addTestSuite(PostgreSQLTests.class); +// suite.addTestSuite(SQLServerTests.class); +// suite.addTestSuite(SybaseTests.class); return suite; } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java index 8c0424d97d..3379574f57 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DTPPlatformTests.java @@ -11,10 +11,16 @@ package org.eclipse.jpt.db.tests.internal.platforms; import java.io.File; import java.io.IOException; +import java.io.OutputStreamWriter; import java.net.URL; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; -import java.util.Collection; -import java.util.NoSuchElementException; +import java.util.Iterator; +import java.util.List; import java.util.Properties; import org.eclipse.core.runtime.CoreException; @@ -23,6 +29,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.datatools.connectivity.ConnectionProfileException; import org.eclipse.datatools.connectivity.IConnectionProfile; +import org.eclipse.datatools.connectivity.IManagedConnection; import org.eclipse.datatools.connectivity.ProfileManager; import org.eclipse.datatools.connectivity.drivers.IDriverMgmtConstants; import org.eclipse.datatools.connectivity.drivers.IPropertySet; @@ -30,385 +37,832 @@ import org.eclipse.datatools.connectivity.drivers.PropertySetImpl; import org.eclipse.datatools.connectivity.drivers.XMLFileManager; import org.eclipse.datatools.connectivity.drivers.jdbc.IJDBCDriverDefinitionConstants; import org.eclipse.datatools.connectivity.internal.ConnectivityPlugin; +import org.eclipse.datatools.connectivity.sqm.core.connection.ConnectionInfo; +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.jpt.db.Catalog; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ConnectionListener; import org.eclipse.jpt.db.ConnectionProfile; -import org.eclipse.jpt.db.ConnectionProfileRepository; +import org.eclipse.jpt.db.ConnectionProfileFactory; +import org.eclipse.jpt.db.ConnectionProfileListener; import org.eclipse.jpt.db.Database; +import org.eclipse.jpt.db.DatabaseFinder; +import org.eclipse.jpt.db.ForeignKey; import org.eclipse.jpt.db.JptDbPlugin; import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.SchemaContainer; +import org.eclipse.jpt.db.Sequence; import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.db.ForeignKey.ColumnPair; import org.eclipse.jpt.db.tests.internal.JptDbTestsPlugin; -import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.ClassTools; +import org.eclipse.jpt.utility.internal.IndentingPrintWriter; import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterators.ResultSetIterator; -import junit.framework.Assert; import junit.framework.TestCase; /** - * Base class for all supported DTP platform. + * Base class for testing DTP wrappers on various databases. */ +@SuppressWarnings("nls") public abstract class DTPPlatformTests extends TestCase { - protected ConnectionProfileRepository connectionRepository; - - private Properties platformProperties; - private String currentDbVendor; - private String currentDbVersion; - - private static final String PLATFORM_CONFIG_DIRECTORY = "config"; //$NON-NLS-1$ - - private static final String PROFILE_NAME_PROPERTY = "profileName"; //$NON-NLS-1$ - private static final String PROFILE_DESCRIPTION_PROPERTY = "profileDescription"; //$NON-NLS-1$ - private static final String USER_NAME_PROPERTY = "userName"; //$NON-NLS-1$ - private static final String USER_PASSWORD_PROPERTY = "userPassword"; //$NON-NLS-1$ - private static final String DB_DRIVER_JAR_PROPERTY = "databasedriverJarList"; //$NON-NLS-1$ - private static final String DB_NAME_PROPERTY = "databaseName"; //$NON-NLS-1$ - private static final String DB_URL_PROPERTY = "databaseUrl"; //$NON-NLS-1$ - - private static final String PROFILE_NAME_DEFAULT = "jpatest"; //$NON-NLS-1$ - private static final String PROFILE_DESCRIPTION_DEFAULT = "JDBC Profile for JPA Testing"; //$NON-NLS-1$ - private static final String USER_NAME_DEFAULT = "userName"; //$NON-NLS-1$ - private static final String USER_PASSWORD_DEFAULT = ""; //$NON-NLS-1$ - private static final String DB_NAME_DEFAULT = "testdb"; //$NON-NLS-1$ - - private static final String MISSING_PROPERTY_MESSAGE = "Enter missing property in platform config file (config/database.properties)"; - - public DTPPlatformTests( String name) { - super( name); - - this.connectionRepository = JptDbPlugin.instance().getConnectionProfileRepository(); - } - - @Override + /** + * The platform properties are loaded from a Java properties file in the + * 'org.eclipse.jpt.db.tests/config' directory. Each database platform has + * its own properties file (e.g. 'derby101.properties'). + */ + private Properties platformProperties; + + /** + * This is the Dali connection profile wrapper. + */ + protected ConnectionProfile connectionProfile; + + + // ********** constants ********** + + private static final String PLATFORM_CONFIG_DIRECTORY = "config"; + + private static final String DB_USER_ID_PROPERTY = "userID"; + private static final String DB_USER_ID_DEFAULT = "user"; + + private static final String DB_PASSWORD_PROPERTY = "password"; + private static final String DB_PASSWORD_DEFAULT = ""; + + private static final String DB_DRIVER_JARS_PROPERTY = "jars"; + // required - no default + + private static final String DB_URL_PROPERTY = "url"; + // required - no default + + private static final String DB_DATABASE_PROPERTY = "database"; + private static final String DB_DATABASE_DEFAULT = "testdb"; + + + + // ********** constructor ********** + + protected DTPPlatformTests(String name) { + super(name); + } + + + // ********** set-up/tear-down ********** + + @Override protected void setUp() throws Exception { - super.setUp(); - - if( this.platformIsNew()) { - this.loadPlatformProperties(); - - this.buildDriverDefinitionFile( IDriverMgmtConstants.DRIVER_FILE); - this.buildConnectionProfile( this.profileName()); - this.currentDbVendor = this.databaseVendor(); - this.currentDbVersion = this.databaseVersion(); - } - this.verifyProfileNamed( this.profileName()); - } - - @Override + super.setUp(); + + this.platformProperties = this.loadPlatformProperties(); + this.buildDTPDriverDefinitionFile(); + this.buildDTPConnectionProfile(); + this.connectionProfile = this.getConnectionProfileFactory().buildConnectionProfile(this.getProfileName(), DatabaseFinder.Default.instance()); + } + + @Override protected void tearDown() throws Exception { - super.tearDown(); + this.connectionProfile = null; + this.platformProperties = null; + + super.tearDown(); + } + + // ***** platform properties file + private Properties loadPlatformProperties() throws IOException { + Properties p = new Properties(); + p.load(this.buildPlatformPropertiesFileURL().openStream()); + return p; + } + + private URL buildPlatformPropertiesFileURL() { + return Platform.getBundle(this.getTestPluginBundleID()).getEntry(this.getPlatformPropertiesFilePath()); + } + + private String getTestPluginBundleID() { + return JptDbTestsPlugin.BUNDLE_ID; + } + + private String getPlatformPropertiesFilePath() { + return this.getPlatformPropertiesDirectoryName() + '/' + this.getPlatformPropertiesFileName(); + } + + private String getPlatformPropertiesDirectoryName() { + return PLATFORM_CONFIG_DIRECTORY; + } + + /** + * Each database platform has a separate properties file in the 'config' + * directory that must be customized by whomever is executing the tests. + */ + protected abstract String getPlatformPropertiesFileName(); + + // ***** driver definition file + private void buildDTPDriverDefinitionFile() throws CoreException { + XMLFileManager.setStorageLocation(this.getDTPDriverDefinitionLocation()); + XMLFileManager.setFileName(this.getDTPDriverFileName()); + + IPropertySet[] sets = XMLFileManager.loadPropertySets(); + for (IPropertySet set : sets) { + if (set.getID().equals(this.getDriverDefinitionID())) { + return; // property sets live across tests + } + } + + XMLFileManager.saveNamedPropertySet(this.buildDTPDriverDefinitionPropertySets()); + + // verify the file was created: + File driverDefinitioneFile = this.getDTPDriverDefinitionLocation().append(this.getDTPDriverFileName()).toFile(); + assertTrue(driverDefinitioneFile.exists()); + } + + private IPath getDTPDriverDefinitionLocation() { + return ConnectivityPlugin.getDefault().getStateLocation(); + } + + private String getDTPDriverFileName() { + return IDriverMgmtConstants.DRIVER_FILE; + } + + private IPropertySet[] buildDTPDriverDefinitionPropertySets() { + IPropertySet[] propertySets = new IPropertySet[1]; + PropertySetImpl propertySet = new PropertySetImpl(this.getDriverName(), this.getDriverDefinitionID()); + propertySet.setProperties(this.getDriverDefinitionID(), this.buildDTPDriverDefinitionProperties()); + propertySets[0] = propertySet; + return propertySets; + } + + protected abstract String getDriverName(); + + protected abstract String getDriverDefinitionID(); + + private Properties buildDTPDriverDefinitionProperties() { + Properties p = new Properties(); + p.setProperty(ConnectionProfile.DRIVER_DEFINITION_TYPE_PROP_ID, this.getDriverDefinitionType()); + p.setProperty(ConnectionProfile.DRIVER_JAR_LIST_PROP_ID, this.getJDBCDriverJarList()); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID, this.getDatabaseVendor()); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_VERSION_PROP_ID, this.getDatabaseVersion()); + p.setProperty(IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID, this.getDriverClass()); + p.setProperty(IJDBCDriverDefinitionConstants.URL_PROP_ID, this.getJDBCURL()); + p.setProperty(IJDBCDriverDefinitionConstants.USERNAME_PROP_ID, this.getUserID()); + p.setProperty(IJDBCDriverDefinitionConstants.PASSWORD_PROP_ID, this.getPassword()); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_NAME_PROP_ID, this.getDatabaseName()); + return p; + } + + protected abstract String getDriverDefinitionType(); + + /** + * The JAR list is workspace-specific and is set in the properties file. + */ + private String getJDBCDriverJarList() { + return this.getRequiredPlatformProperty(DB_DRIVER_JARS_PROPERTY); + } + + protected abstract String getDatabaseVendor(); + + protected abstract String getDatabaseVersion(); + + protected abstract String getDriverClass(); + + /** + * The database URL is workspace-specific and is set in the properties file + * for some databases. + */ + private String getJDBCURL() { + return this.platformProperties.getProperty(DB_URL_PROPERTY, this.getDefaultJDBCURL()); + } + + protected String getDefaultJDBCURL() { + return ""; + } + + /** + * The user ID is optional and can be set in the properties file. + */ + protected String getUserID() { + return this.platformProperties.getProperty(DB_USER_ID_PROPERTY, DB_USER_ID_DEFAULT); + } + + /** + * The password is optional and can be set in the properties file. + */ + private String getPassword() { + return this.platformProperties.getProperty(DB_PASSWORD_PROPERTY, DB_PASSWORD_DEFAULT); + } + + /** + * The database name is optional and can be set in the properties file. + */ + protected String getDatabaseName() { + return this.platformProperties.getProperty(DB_DATABASE_PROPERTY, DB_DATABASE_DEFAULT); + } + + // ***** DTP connection profile + private void buildDTPConnectionProfile() throws ConnectionProfileException { + if (this.getDTPProfileManager().getProfileByName(this.getProfileName()) != null) { + return; // profiles live across tests + } + this.createProfile(this.getProfileName()); + assertNotNull(this.getDTPProfileManager().getProfileByName(this.getProfileName())); + } + + protected void createProfile(String profileName) throws ConnectionProfileException { + this.getDTPProfileManager().createProfile( + profileName, + this.getProfileDescription(), + this.getProviderID(), + this.buildDTPConnectionProfileProperties() + ); + } + + protected abstract String getProfileName(); + + protected abstract String getProfileDescription(); + + protected String getProviderID() { + return ConnectionProfile.CONNECTION_PROFILE_TYPE; + } + + private Properties buildDTPConnectionProfileProperties() { + Properties p = new Properties(); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_NAME_PROP_ID, this.getDatabaseName()); + p.setProperty(IJDBCDriverDefinitionConstants.USERNAME_PROP_ID, this.getUserID()); + p.setProperty(IJDBCDriverDefinitionConstants.PASSWORD_PROP_ID, this.getPassword()); + p.setProperty(ConnectionProfile.DRIVER_DEFINITION_PROP_ID, this.getDriverDefinitionID()); + + p.setProperty(IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID, this.getDriverClass()); + p.setProperty(IJDBCDriverDefinitionConstants.URL_PROP_ID, this.getJDBCURL()); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID, this.getDatabaseVendor()); + p.setProperty(IJDBCDriverDefinitionConstants.DATABASE_VERSION_PROP_ID, this.getDatabaseVersion()); + + p.setProperty(ConnectionProfile.DATABASE_SAVE_PWD_PROP_ID, this.passwordIsSaved()); + return p; + } + + private String passwordIsSaved() { + return "true"; } // ********** tests ********** + public void testConnectionProfileListener() throws ConnectionProfileException { + TestConnectionProfileListener listener = new TestConnectionProfileListener(); + this.getConnectionProfileFactory().addConnectionProfileListener(listener); + + String cpName1 = this.getProfileName() + "1"; + this.createProfile(cpName1); + IConnectionProfile dtpCP = this.getDTPProfileManager().getProfileByName(cpName1); + assertNotNull(dtpCP); + + assertEquals(cpName1, listener.addedName); + listener.clear(); + + String cpName2 = this.getProfileName() + "2"; + this.getDTPProfileManager().modifyProfile(dtpCP, cpName2, null); + assertEquals(cpName1, listener.renamedOldName); + assertEquals(cpName2, listener.renamedNewName); + listener.clear(); + + ConnectionProfile cp = this.getConnectionProfileFactory().buildConnectionProfile(cpName2); + assertNotNull(cp); + + this.getDTPProfileManager().deleteProfile(dtpCP); + assertEquals(cpName2, listener.removedName); + listener.clear(); + + cp = this.getConnectionProfileFactory().buildConnectionProfile(cpName2); + assertNull(cp); + + this.getConnectionProfileFactory().removeConnectionProfileListener(listener); + } + + public void testName() { + assertEquals(this.getProfileName(), this.connectionProfile.getName()); + } + public void testConnection() throws Exception { + assertTrue(this.connectionProfile.isInactive()); + assertTrue(this.connectionProfile.isDisconnected()); + this.connectionProfile.connect(); + assertTrue(this.connectionProfile.isActive()); + assertTrue(this.connectionProfile.isConnected()); + + this.verifyDatabaseVersionNumber(); + this.verifyDatabaseVendor(); + this.verifyDatabaseContent(); + + this.connectionProfile.disconnect(); + assertTrue(this.connectionProfile.isInactive()); + assertTrue(this.connectionProfile.isDisconnected()); + } + + private void verifyDatabaseVersionNumber() { + Database database = this.connectionProfile.getDatabase(); + assertNotNull(database); + + String actual = database.getVersion(); + String expected = this.getDatabaseVersion(); + String errorMessage = "expected: " + expected + " - actual: " + actual; + // partial match is good enough + assertTrue(errorMessage, actual.indexOf(expected) != -1); + } - this.connect(); - - this.verifyDatabaseVersionNumber(); - this.verifyDatabaseContent(); - - this.disconnect(); - } - - public void testGetProfiles() { - // Getting the profile directly from DTP ProfileManager - IConnectionProfile[] profiles = ProfileManager.getInstance().getProfiles(); - Assert.assertNotNull( profiles); - Assert.assertTrue( profiles.length > 0); - } - - public void testGetProfilesByProvider() { - // Get Profiles By ProviderID - IConnectionProfile[] profiles = ProfileManager.getInstance().getProfileByProviderID( this.getProfile().getProviderID()); - Assert.assertNotNull( profiles); - Assert.assertTrue( profiles.length > 0); - } - - public void testGetProfileByName() { - // Get Profile By Name - IConnectionProfile dtpProfile = this.getDTPProfile(); - Assert.assertNotNull( dtpProfile); - Assert.assertTrue( dtpProfile.getName().equals( this.profileName())); - } - - public void testGetProfileByInstanceId() { - // Get Profile By InstanceID - IConnectionProfile dtpProfile = ProfileManager.getInstance().getProfileByInstanceID( this.getProfile().getInstanceID()); - Assert.assertNotNull( dtpProfile); - Assert.assertTrue( dtpProfile.getName().equals( this.profileName())); - } - - public void testWorkingOffline() { - - if( this.getProfile().supportsWorkOfflineMode()) { - - if( ! this.getProfile().canWorkOffline()) { - this.connect(); - this.saveWorkOfflineData(); - this.disconnect(); - - Assert.assertTrue( this.getProfile().canWorkOffline()); + private void verifyDatabaseVendor() { + Database database = this.connectionProfile.getDatabase(); + String actual = database.getVendor(); + String expected = this.getDatabaseVendor(); + assertEquals(expected, actual); + } + + private void verifyDatabaseContent() { + Database database = this.connectionProfile.getDatabase(); + assertTrue(database.schemataSize() > 0); + + Schema schema = database.getDefaultSchema(); + if (schema != null) { + if (schema.tablesSize() > 0) { + Table table = schema.tables().next(); + assertTrue(table.columnsSize() >= 0); + assertTrue(table.primaryKeyColumnsSize() >= 0); + assertTrue(table.foreignKeysSize() >= 0); } - this.workOffline(); - - Assert.assertTrue( this.getProfile().isActive()); - Assert.assertTrue( this.getProfile().isWorkingOffline()); - - this.disconnect(); - } - } - - // ********** internal tests ********** - - private void verifyDatabaseVersionNumber() { - Database database = this.getProfile().getDatabase(); - Assert.assertNotNull( database); - - String actualVersionNumber = database.getVersion(); - String expectedVersionNumber = this.databaseVersion(); - String errorMessage = "Expected version number: " + expectedVersionNumber + " but the actual version number was: " + actualVersionNumber; - assertTrue( errorMessage, actualVersionNumber.indexOf( expectedVersionNumber) != -1); - - String actualVendor = database.getVendor(); - String expectedVendor = this.databaseVendor(); - errorMessage = "Expected vendor: " + expectedVendor + " but the actual vendor was: " + actualVendor; - assertEquals( errorMessage, actualVendor, expectedVendor); - } - - private void verifyDatabaseContent() { - Database database = this.getProfile().getDatabase(); - Assert.assertTrue( database.schemataSize() > 0); - - Schema schema = database.schemaNamed( this.getProfile().getUserName()); - if( schema != null) { - Assert.assertTrue( schema.sequencesSize() >= 0); + } + } + + public void testOffline() { + if ( ! this.connectionProfile.supportsWorkOfflineMode()) { + return; + } + + this.prepareForOfflineWork(); + + IStatus status = this.connectionProfile.workOffline(); + assertTrue(status.isOK()); + assertTrue(this.connectionProfile.isActive()); + assertTrue(this.connectionProfile.isWorkingOffline()); + + this.connectionProfile.disconnect(); + assertTrue(this.connectionProfile.isInactive()); + assertTrue(this.connectionProfile.isDisconnected()); + } + + protected void prepareForOfflineWork() { + if ( ! this.connectionProfile.canWorkOffline()) { + this.connectionProfile.connect(); + IStatus status = this.connectionProfile.saveWorkOfflineData(); + assertTrue(status.isOK()); + this.connectionProfile.disconnect(); + assertTrue(this.connectionProfile.canWorkOffline()); + } + } + + public void testConnectionListenerConnect() { + assertTrue(this.connectionProfileHasNoListeners()); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + assertTrue(this.connectionProfileHasAnyListeners()); + + this.connectionProfile.connect(); + assertSame(this.connectionProfile, listener.openedProfile); + listener.clear(); + + this.connectionProfile.disconnect(); + assertSame(this.connectionProfile, listener.okToCloseProfile); + assertSame(this.connectionProfile, listener.aboutToCloseProfile); + assertSame(this.connectionProfile, listener.closedProfile); + + this.connectionProfile.removeConnectionListener(listener); + assertTrue(this.connectionProfileHasNoListeners()); + } + + public void testConnectionListenerOffline() { + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.prepareForOfflineWork(); + listener.clear(); + + this.connectionProfile.workOffline(); + assertSame(this.connectionProfile, listener.openedProfile); + listener.clear(); + + this.connectionProfile.disconnect(); + assertSame(this.connectionProfile, listener.okToCloseProfile); + assertSame(this.connectionProfile, listener.aboutToCloseProfile); + assertSame(this.connectionProfile, listener.closedProfile); + listener.clear(); + + this.connectionProfile.removeConnectionListener(listener); + } + + public void testConnectionListenerDatabase() { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + ((ICatalogObject) this.getDTPDatabase()).refresh(); + assertSame(this.connectionProfile.getDatabase(), listener.changedDatabase); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testConnectionListenerCatalog() { + this.connectionProfile.connect(); + if ( ! this.connectionProfile.getDatabase().supportsCatalogs()) { + this.connectionProfile.disconnect(); + return; + } - Object[] tableNames = CollectionTools.array( schema.tableNames()); - if( tableNames.length >= 1) { - Table table = schema.tableNamed(( String)tableNames[ 0]); - Assert.assertTrue( table.columnsSize() >= 0); - Assert.assertTrue( table.foreignKeysSize() >= 0); - Assert.assertTrue( table.primaryKeyColumnsSize() >= 0); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + // take the first catalog + org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog = this.getFirstDTPCatalog(); + Catalog catalog = this.connectionProfile.getDatabase().getCatalogNamed(dtpCatalog.getName()); + ((ICatalogObject) dtpCatalog).refresh(); + assertSame(catalog, listener.changedCatalog); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testConnectionListenerSchema() { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + org.eclipse.datatools.modelbase.sql.schema.Schema dtpSchema = null; + Schema schema = null; + if (this.connectionProfile.getDatabase().supportsCatalogs()) { + org.eclipse.datatools.modelbase.sql.schema.Catalog dtpCatalog = this.getFirstDTPCatalog(); + dtpSchema = (org.eclipse.datatools.modelbase.sql.schema.Schema) dtpCatalog.getSchemas().get(0); + schema = this.connectionProfile.getDatabase().getCatalogNamed(dtpCatalog.getName()).getSchemaNamed(dtpSchema.getName()); + } else { + dtpSchema = (org.eclipse.datatools.modelbase.sql.schema.Schema) this.getDTPDatabase().getSchemas().get(0); + schema = this.connectionProfile.getDatabase().getSchemaNamed(dtpSchema.getName()); + } + ((ICatalogObject) dtpSchema).refresh(); + assertSame(schema, listener.changedSchema); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + + // ********** convenience methods ********** + + protected ConnectionProfileFactory getConnectionProfileFactory() { + return JptDbPlugin.instance().getConnectionProfileFactory(); + } + + protected ConnectionProfile getConnectionProfile() { + return this.connectionProfile; + } + + protected Database getDatabase() { + return this.connectionProfile.getDatabase(); + } + + protected Catalog getCatalogNamed(String catalogName) { + return this.connectionProfile.getDatabase().getCatalogNamed(catalogName); + } + + protected Schema getSchemaNamed(String schemaName) { + return this.connectionProfile.getDatabase().getSchemaNamed(schemaName); + } + + protected String getRequiredPlatformProperty(String propertyKey) { + String propertyValue = this.platformProperties.getProperty(propertyKey); + if (StringTools.stringIsEmpty(propertyValue)) { + throw new IllegalArgumentException("The database platform properties file '" + this.getPlatformPropertiesFilePath() + + "' is missing a value for the property '" + propertyKey + "'."); + } + return propertyValue; + } + + protected boolean connectionProfileHasAnyListeners() { + return connectionProfileHasAnyListeners(this.connectionProfile); + } + + protected static boolean connectionProfileHasAnyListeners(ConnectionProfile cp) { + return ((Boolean) ClassTools.executeMethod(cp, "hasAnyListeners")).booleanValue(); + } + + protected boolean connectionProfileHasNoListeners() { + return connectionProfileHasNoListeners(this.connectionProfile); + } + + protected static boolean connectionProfileHasNoListeners(ConnectionProfile cp) { + return ((Boolean) ClassTools.executeMethod(cp, "hasNoListeners")).booleanValue(); + } + + + // ********** DTP model ********** + + protected ProfileManager getDTPProfileManager() { + return ProfileManager.getInstance(); + } + + protected IConnectionProfile getDTPConnectionProfile() { + return getDTPConnectionProfile(this.connectionProfile); + } + + protected static IConnectionProfile getDTPConnectionProfile(ConnectionProfile cp) { + return (IConnectionProfile) ClassTools.fieldValue(cp, "dtpConnectionProfile"); + } + + protected IManagedConnection getDTPManagedConnection() { + return (IManagedConnection) ClassTools.fieldValue(this.connectionProfile, "dtpManagedConnection"); + } + + protected org.eclipse.datatools.modelbase.sql.schema.Database getDTPDatabase() { + return getDTPDatabase(this.connectionProfile.getDatabase()); + } + + protected static org.eclipse.datatools.modelbase.sql.schema.Database getDTPDatabase(Database database) { + return (org.eclipse.datatools.modelbase.sql.schema.Database) ClassTools.fieldValue(database, "dtpDatabase"); + } + + protected org.eclipse.datatools.modelbase.sql.schema.Catalog getFirstDTPCatalog() { + return (org.eclipse.datatools.modelbase.sql.schema.Catalog) this.getDTPDatabase().getCatalogs().get(0); + } + + protected org.eclipse.datatools.modelbase.sql.schema.Catalog getDTPCatalogNamed(String name) { + return getDTPCatalog(this.getDatabase().getCatalogNamed(name)); + } + + protected static org.eclipse.datatools.modelbase.sql.schema.Catalog getDTPCatalog(Catalog catalog) { + return (org.eclipse.datatools.modelbase.sql.schema.Catalog) ClassTools.fieldValue(catalog, "dtpCatalog"); + } + + protected org.eclipse.datatools.modelbase.sql.schema.Schema getDTPSchemaNamed(String name) { + return getDTPSchema(this.getDatabase().getSchemaNamed(name)); + } + + protected static org.eclipse.datatools.modelbase.sql.schema.Schema getDTPSchema(Schema schema) { + return (org.eclipse.datatools.modelbase.sql.schema.Schema) ClassTools.fieldValue(schema, "dtpSchema"); + } + + + // ********** execute SQL ********** + + /** + * ignore any errors (useful for dropping database objects that might + * not be there) + */ + protected void executeUpdateIgnoreErrors(String sql) { + try { + this.executeUpdate(sql); + } catch (Exception ex) { + // ignore + } + } + + protected void executeUpdate(String sql) throws SQLException { + Statement jdbcStatement = this.createJDBCStatement(); + jdbcStatement.executeUpdate(sql); + jdbcStatement.close(); + } + + protected List<Object[]> execute(String sql) throws SQLException { + Statement jdbcStatement = this.createJDBCStatement(); + jdbcStatement.execute(sql); + ResultSet resultSet = jdbcStatement.getResultSet(); + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + ArrayList<Object[]> rows = new ArrayList<Object[]>(); + for (Iterator<Object[]> stream = new ResultSetIterator<Object[]>(resultSet, new LocalResultSetIteratorAdapter(columnCount)); stream.hasNext(); ) { + rows.add(stream.next()); + } + jdbcStatement.close(); + return rows; + } + + public class LocalResultSetIteratorAdapter implements ResultSetIterator.Adapter<Object[]> { + private int columnCount; + public LocalResultSetIteratorAdapter(int columnCount) { + super(); + this.columnCount = columnCount; + } + public Object[] buildNext(ResultSet rs) throws SQLException { + Object[] row = new Object[this.columnCount]; + for (int i = 0; i < row.length; i++) { + row[i] = rs.getObject(i + 1); } + return row; } - } - - private void verifyProfileNamed( String profileName) { - - ConnectionProfile profile = this.getProfileNamed( profileName); - Assert.assertTrue( "ConnectionProfile not found", profileName.equals( profile.getName())); - } - - // ***** Platform specific behavior ***** - - protected abstract String databaseVendor(); - protected abstract String databaseVersion(); - - protected abstract String driverName(); - protected abstract String driverDefinitionType(); - protected abstract String driverDefinitionId(); - protected abstract String driverClass(); - - protected abstract String getConfigName(); - - // ***** Behavior ***** - - protected void connect() { - - this.getProfile().connect(); - Assert.assertTrue( "Could not connect.", this.getProfile().isActive()); - Assert.assertFalse( "Connection corrupted.", this.getProfile().isWorkingOffline()); - } - - protected void disconnect() { - - this.getProfile().disconnect(); - Assert.assertFalse( "Disconnect failed.", this.getProfile().isActive()); - } - - private void workOffline() { - IStatus status = this.getProfile().workOffline(); - - Assert.assertTrue( "Could not work offline.", status.isOK()); - } - - private void saveWorkOfflineData() { - IStatus status = this.getProfile().saveWorkOfflineData(); - - Assert.assertTrue( "Could not save offline data.", status.isOK()); - } - - // ********** queries ********** - - protected Schema getSchemaNamed( String schemaName) { - - return this.getProfile().getDatabase().schemaNamed( schemaName); - } - - protected Collection<Table> getTables() { - - Schema schema = this.getSchemaNamed( this.getProfile().getUserName()); - if( schema == null) { - return new ArrayList<Table>(); - } - return CollectionTools.collection( schema.tables()); - } - - protected Table getTableNamed( String tableName) { - - Schema schema = this.getSchemaNamed( this.getProfile().getUserName()); - Assert.assertNotNull( schema); - - return schema.tableNamed( tableName); - } - - protected String providerId() { - return ConnectionProfile.CONNECTION_PROFILE_TYPE; - } - - protected String passwordIsSaved() { - return "true"; - } - - - protected IConnectionProfile getDTPProfile() { - return ProfileManager.getInstance().getProfileByName( this.profileName()); - } - - protected String profileName() { - return this.platformProperties.getProperty( PROFILE_NAME_PROPERTY, PROFILE_NAME_DEFAULT); - } - - protected String profileDescription() { - return this.platformProperties.getProperty( PROFILE_DESCRIPTION_PROPERTY, PROFILE_DESCRIPTION_DEFAULT); - } - - protected String userName() { - return this.platformProperties.getProperty( USER_NAME_PROPERTY, USER_NAME_DEFAULT); - } - - protected String userPassword() { - return this.platformProperties.getProperty( USER_PASSWORD_PROPERTY, USER_PASSWORD_DEFAULT); - } - - protected String databaseName() { - return this.platformProperties.getProperty( DB_NAME_PROPERTY, DB_NAME_DEFAULT); - } - - protected String databasedriverJarList() { - String dbDriverJarList = this.platformProperties.getProperty( DB_DRIVER_JAR_PROPERTY); - if ( StringTools.stringIsEmpty( dbDriverJarList)) { - throw new NoSuchElementException( MISSING_PROPERTY_MESSAGE); - } - return dbDriverJarList; - } - - protected String databaseUrl() { - String dbUrl = this.platformProperties.getProperty( DB_URL_PROPERTY); - if ( StringTools.stringIsEmpty( dbUrl)) { - throw new NoSuchElementException( MISSING_PROPERTY_MESSAGE); - } - return dbUrl; - } - - protected ConnectionProfile getProfile() { - - return this.getProfileNamed( this.profileName()); - } - - protected ConnectionProfile getProfileNamed( String profileName) { - - return this.connectionRepository.connectionProfileNamed( profileName); - } - - private String getTestPluginBundleId() { - return JptDbTestsPlugin.BUNDLE_ID; } - private IPath getDriverDefinitionLocation() { - return ConnectivityPlugin.getDefault().getStateLocation(); + protected Statement createJDBCStatement() throws SQLException { + return this.getJDBCConnection().createStatement(); + } + + protected Connection getJDBCConnection() { + return ((ConnectionInfo) this.getDTPManagedConnection().getConnection().getRawConnection()).getSharedConnection(); + } + + + // ********** dump database schema ********** + + /** + * dump all the database metadata to the console + */ + protected void dumpDatabase() { + IndentingPrintWriter pw = new IndentingPrintWriter(new OutputStreamWriter(System.out)); + // synchronize the console so everything is contiguous + synchronized (System.out) { + this.dumpDatabaseOn(pw); + } + pw.flush(); + } + + protected void dumpDatabaseOn(IndentingPrintWriter pw) { + Database database = this.connectionProfile.getDatabase(); + pw.print("database: "); + pw.println(database.getName()); + if (database.supportsCatalogs()) { + for (Iterator<Catalog> stream = database.catalogs(); stream.hasNext(); ) { + this.dumpCatalogOn(stream.next(), pw); + } + } else { + this.dumpSchemaOnContainerOn(database, pw); + } + } + + protected void dumpCatalogOn(Catalog catalog, IndentingPrintWriter pw) { + pw.print("catalog: "); + pw.println(catalog.getName()); + pw.indent(); + this.dumpSchemaOnContainerOn(catalog, pw); + pw.undent(); + } + + protected void dumpSchemaOnContainerOn(SchemaContainer schemaContainer, IndentingPrintWriter pw) { + for (Iterator<Schema> stream = schemaContainer.schemata(); stream.hasNext(); ) { + this.dumpSchemaOn(stream.next(), pw); + } + } + + protected void dumpSchemaOn(Schema schema, IndentingPrintWriter pw) { + pw.print("schema: "); + pw.println(schema.getName()); + pw.indent(); + for (Iterator<Table> stream = schema.tables(); stream.hasNext(); ) { + this.dumpTableOn(stream.next(), pw); + } + for (Iterator<Sequence> stream = schema.sequences(); stream.hasNext(); ) { + this.dumpSequenceOn(stream.next(), pw); + } + pw.undent(); + } + + protected void dumpTableOn(Table table, IndentingPrintWriter pw) { + pw.print("table: "); + pw.println(table.getName()); + pw.indent(); + for (Iterator<Column> stream = table.columns(); stream.hasNext(); ) { + this.dumpColumnOn(stream.next(), pw); + } + for (Iterator<ForeignKey> stream = table.foreignKeys(); stream.hasNext(); ) { + this.dumpForeignKeyOn(stream.next(), pw); + } + pw.undent(); + } + + protected void dumpColumnOn(Column column, IndentingPrintWriter pw) { + pw.print("column: "); + pw.print(column.getName()); + pw.print(" : "); + pw.print(column.getDataTypeName()); + if (column.isPrimaryKeyColumn()) { + pw.print(" [primary key]"); + } + pw.println(); + } + + protected void dumpForeignKeyOn(ForeignKey foreignKey, IndentingPrintWriter pw) { + pw.print("foreign key: "); + pw.print(foreignKey.getName()); + pw.print("=>"); + pw.print(foreignKey.getReferencedTable().getName()); + pw.print(" ("); + for (Iterator<ColumnPair> stream = foreignKey.columnPairs(); stream.hasNext(); ) { + ColumnPair cp = stream.next(); + pw.print(cp.getBaseColumn().getName()); + pw.print("=>"); + pw.print(cp.getReferencedColumn().getName()); + if (stream.hasNext()) { + pw.print(", "); + } + } + pw.print(')'); + pw.println(); + } + + protected void dumpSequenceOn(Sequence sequence, IndentingPrintWriter pw) { + pw.print("sequence: "); + pw.println(sequence.getName()); + } + + + // ********** connection profile listener ********** + + protected class TestConnectionProfileListener implements ConnectionProfileListener { + public String addedName; + public String removedName; + public String renamedOldName; + public String renamedNewName; + + public void connectionProfileAdded(String name) { + this.addedName = name; + } + public void connectionProfileRemoved(String name) { + this.removedName = name; + } + public void connectionProfileRenamed(String oldName, String newName) { + this.renamedOldName = oldName; + this.renamedNewName = newName; + } + public void clear() { + this.addedName = null; + this.removedName = null; + this.renamedOldName = null; + this.renamedNewName = null; + } } - - private String getConfigPath() { - return this.getConfigDir() + "/" + this.getConfigName(); - } - - private String getConfigDir() { - return PLATFORM_CONFIG_DIRECTORY; - } - - private boolean platformIsNew() { - return( !this.databaseVendor().equals( this.currentDbVendor) || this.databaseVersion().equals( this.currentDbVersion)); - } - - private void loadPlatformProperties() throws IOException { - - if( this.platformProperties == null) { - URL configUrl = Platform.getBundle( this.getTestPluginBundleId()).getEntry( this.getConfigPath()); - - this.platformProperties = new Properties(); - this.platformProperties.load( configUrl.openStream()); - } - } - - private Properties buildDriverProperties() { - Properties driverProperties = new Properties(); - driverProperties.setProperty( ConnectionProfile.DRIVER_DEFINITION_TYPE_PROP_ID, this.driverDefinitionType()); - driverProperties.setProperty( ConnectionProfile.DRIVER_JAR_LIST_PROP_ID, this.databasedriverJarList()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.USERNAME_PROP_ID, this.userName()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID, this.driverClass()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_NAME_PROP_ID, this.databaseName()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.PASSWORD_PROP_ID, this.userPassword()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.URL_PROP_ID, this.databaseUrl()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID, this.databaseVendor()); - driverProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_VERSION_PROP_ID, this.databaseVersion()); - return driverProperties; - } - - private Properties buildBasicProperties() { - Properties basicProperties = new Properties(); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_NAME_PROP_ID, this.databaseName()); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.USERNAME_PROP_ID, this.userName()); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.PASSWORD_PROP_ID, this.userPassword()); - basicProperties.setProperty( ConnectionProfile.DRIVER_DEFINITION_PROP_ID, this.driverDefinitionId()); - - basicProperties.setProperty( IJDBCDriverDefinitionConstants.DRIVER_CLASS_PROP_ID, this.driverClass()); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.URL_PROP_ID, this.databaseUrl()); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_VENDOR_PROP_ID, this.databaseVendor()); - basicProperties.setProperty( IJDBCDriverDefinitionConstants.DATABASE_VERSION_PROP_ID, this.databaseVersion()); - - basicProperties.setProperty( ConnectionProfile.DATABASE_SAVE_PWD_PROP_ID, this.passwordIsSaved()); - return basicProperties; - } - - private void buildConnectionProfile( String profileName) throws ConnectionProfileException { - - ProfileManager profileManager = ProfileManager.getInstance(); - Assert.assertNotNull( profileManager); - - IConnectionProfile dtpProfile = this.getDTPProfile(); - if( dtpProfile == null) { - Properties basicProperties = buildBasicProperties(); - ProfileManager.getInstance().createProfile( profileName, this.profileDescription(), this.providerId(), basicProperties); - } - } - - private void buildDriverDefinitionFile( String driverFileName) throws CoreException { - - XMLFileManager.setStorageLocation( this.getDriverDefinitionLocation()); - XMLFileManager.setFileName( driverFileName); - IPropertySet[] propsets = new IPropertySet[ 1]; - String driverName = this.driverName(); - String driverId = this.driverDefinitionId(); - PropertySetImpl propertySet = new PropertySetImpl( driverName, driverId); - propertySet.setProperties( driverId, this.buildDriverProperties()); - propsets[ 0] = propertySet; - - XMLFileManager.saveNamedPropertySet( propsets); - - File driverDefinitioneFile = this.getDriverDefinitionLocation().append( driverFileName).toFile(); - Assert.assertTrue( driverDefinitioneFile.exists()); - } - + + + // ********** connection listener ********** + + protected class TestConnectionListener implements ConnectionListener { + public ConnectionProfile openedProfile; + public ConnectionProfile modifiedProfile; + public ConnectionProfile okToCloseProfile; + public ConnectionProfile aboutToCloseProfile; + public ConnectionProfile closedProfile; + public Database changedDatabase; + public Catalog changedCatalog; + public Schema changedSchema; + public Sequence changedSequence; + public Table changedTable; + public Column changedColumn; + public ForeignKey changedForeignKey; + + public void opened(ConnectionProfile profile) { + this.openedProfile = profile; + } + public void modified(ConnectionProfile profile) { + this.modifiedProfile = profile; + } + public boolean okToClose(ConnectionProfile profile) { + this.okToCloseProfile = profile; + return true; + } + public void aboutToClose(ConnectionProfile profile) { + this.aboutToCloseProfile = profile; + } + public void closed(ConnectionProfile profile) { + this.closedProfile = profile; + } + public void databaseChanged(ConnectionProfile profile, Database database) { + this.changedDatabase = database; + } + public void catalogChanged(ConnectionProfile profile, Catalog catalog) { + this.changedCatalog = catalog; + } + public void schemaChanged(ConnectionProfile profile, Schema schema) { + this.changedSchema = schema; + } + public void sequenceChanged(ConnectionProfile profile, Sequence sequence) { + this.changedSequence = sequence; + } + public void tableChanged(ConnectionProfile profile, Table table) { + this.changedTable = table; + } + public void columnChanged(ConnectionProfile profile, Column column) { + this.changedColumn = column; + } + public void foreignKeyChanged(ConnectionProfile profile, ForeignKey foreignKey) { + this.changedForeignKey = foreignKey; + } + public void clear() { + this.openedProfile = null; + this.modifiedProfile = null; + this.okToCloseProfile = null; + this.aboutToCloseProfile = null; + this.closedProfile = null; + this.changedDatabase = null; + this.changedCatalog = null; + this.changedSchema = null; + this.changedSequence = null; + this.changedTable = null; + this.changedColumn = null; + this.changedForeignKey = null; + } + } + } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Derby101Tests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Derby101Tests.java deleted file mode 100644 index 2244b0e623..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Derby101Tests.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * 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 - ******************************************************************************/ -package org.eclipse.jpt.db.tests.internal.platforms; - - -/** - * Derby 10.1 Embedded Driver Test - */ -public class Derby101Tests extends DTPPlatformTests { - - public Derby101Tests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "Derby"; - } - - @Override - protected String databaseVersion() { - return "10.1"; - } - - @Override - protected String providerId() { - return "org.eclipse.datatools.connectivity.db.derby.embedded.connectionProfile"; - } - - @Override - protected String driverName() { - return "Derby Embedded JDBC Driver"; - } - - @Override - protected String driverDefinitionType() { - return "org.eclipse.datatools.connectivity.db.derby101.genericDriverTemplate"; - } - - @Override - protected String driverDefinitionId() { - return "DriverDefn.Derby Embedded JDBC Driver"; - } - - @Override - protected String driverClass() { - return "org.apache.derby.jdbc.EmbeddedDriver"; - } - - @Override - protected String getConfigName() { - return "derby101.properties"; - } - -} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DerbyTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DerbyTests.java new file mode 100644 index 0000000000..dd5e46b91a --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/DerbyTests.java @@ -0,0 +1,395 @@ +/******************************************************************************* + * 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 + ******************************************************************************/ +package org.eclipse.jpt.db.tests.internal.platforms; + +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.jpt.db.Catalog; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; + +/** + * Derby 10.1 Embedded Driver Test + */ +@SuppressWarnings("nls") +public class DerbyTests extends DTPPlatformTests { + + public DerbyTests(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Override + protected String getPlatformPropertiesFileName() { + return "derby.properties"; + } + + @Override + protected String getDriverName() { + return "Derby Embedded JDBC Driver"; + } + + @Override + protected String getDriverDefinitionID() { + return "DriverDefn.Derby Embedded JDBC Driver"; + } + + @Override + protected String getDriverDefinitionType() { + return "org.eclipse.datatools.connectivity.db.derby101.genericDriverTemplate"; + } + + @Override + protected String getDatabaseVendor() { + return "Derby"; + } + + @Override + protected String getDatabaseVersion() { + return "10.1"; + } + + @Override + protected String getDriverClass() { + return "org.apache.derby.jdbc.EmbeddedDriver"; + } + + @Override + protected String getProfileName() { + return "Derby_10.1_Embedded"; + } + + @Override + protected String getProfileDescription() { + return "Derby 10.1 Embedded JDBC Profile [Test]"; + } + + @Override + protected String getProviderID() { + return "org.eclipse.datatools.connectivity.db.derby.embedded.connectionProfile"; + } + + public void testSchema() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("TEST1"); + this.dropSchema("TEST2"); + + this.executeUpdate("CREATE SCHEMA TEST1"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema1 = this.getDatabase().getSchemaNamed("TEST1"); + assertNotNull(schema1); + Catalog catalog = this.getDatabase().getCatalogNamed(""); // Derby's only catalog + Schema schema1a = catalog.getSchemaNamed("TEST1"); + assertNotNull(schema1a); + assertSame(schema1, schema1a); // same schema should be returned by both database and catalog + + this.executeUpdate("CREATE SCHEMA TEST2"); + Schema schema2 = this.getDatabase().getSchemaNamed("TEST2"); + assertNull(schema2); // should be null until refresh + + ((ICatalogObject) getDTPCatalog(catalog)).refresh(); + assertSame(catalog, listener.changedCatalog); + assertSame(catalog, this.getDatabase().getCatalogNamed("")); + + schema2 = this.getDatabase().getSchemaNamed("TEST2"); + assertNotNull(schema2); + Schema schema2a = catalog.getSchemaNamed("TEST2"); + assertNotNull(schema2a); + assertSame(schema2, schema2a); + assertNotSame(schema1, catalog.getSchemaNamed("TEST1")); // we should have a new schema after the refresh + + this.dropSchema("TEST2"); + this.dropSchema("TEST1"); + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testSchemaLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("LOOKUP_TEST"); + this.dropSchema("\"lookup_TEST\""); + + this.executeUpdate("CREATE SCHEMA LOOKUP_TEST"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + assertNotNull(this.getDatabase().getSchemaNamed("LOOKUP_TEST")); + assertNotNull(this.getDatabase().getSchemaNamed("lookup_test")); + assertNotNull(this.getDatabase().getSchemaNamed("lookup_TEST")); + assertNotNull(this.getDatabase().getSchemaNamed("\"LOOKUP_TEST\"")); + assertNull(this.getDatabase().getSchemaNamed("\"lookup_TEST\"")); + + this.dropSchema("LOOKUP_TEST"); + + this.executeUpdate("CREATE SCHEMA \"lookup_TEST\""); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + assertNull(this.getDatabase().getSchemaNamed("LOOKUP_TEST")); + assertNull(this.getDatabase().getSchemaNamed("lookup_test")); + assertNull(this.getDatabase().getSchemaNamed("lookup_TEST")); + assertNull(this.getDatabase().getSchemaNamed("\"LOOKUP_TEST\"")); + assertNotNull(this.getDatabase().getSchemaNamed("\"lookup_TEST\"")); + + this.dropSchema("\"lookup_TEST\""); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testSchemaAnnotationIdentifier() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("LOOKUP_TEST"); + this.dropSchema("\"lookup_TEST\""); + + this.executeUpdate("CREATE SCHEMA lookup_test"); // this gets folded to uppercase + this.executeUpdate("CREATE SCHEMA \"lookup_TEST\""); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getSchemaNamed("LOOKUP_TEST"); + assertEquals("LOOKUP_TEST", schema.getAnnotationIdentifier()); + assertEquals("LOOKUP_TEST", schema.getAnnotationIdentifier("LookupTest")); + assertNull(schema.getAnnotationIdentifier("Lookup_Test")); + + schema = this.getDatabase().getSchemaNamed("lookup_test"); + assertEquals("LOOKUP_TEST", schema.getAnnotationIdentifier()); + + schema = this.getDatabase().getSchemaNamed("\"lookup_TEST\""); + assertEquals("\"lookup_TEST\"", schema.getAnnotationIdentifier()); + assertEquals("\"lookup_TEST\"", schema.getAnnotationIdentifier("lookup_TEST")); + + this.dropSchema("\"lookup_TEST\""); + this.dropSchema("LOOKUP_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testTable() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("TABLE_TEST", "FOO_BAZ"); + this.dropTable("TABLE_TEST", "BAZ"); + this.dropTable("TABLE_TEST", "FOO"); + this.dropTable("TABLE_TEST", "BAR"); + this.dropSchema("TABLE_TEST"); + + this.executeUpdate("CREATE SCHEMA TABLE_TEST"); + this.executeUpdate("SET SCHEMA = TABLE_TEST"); + + this.executeUpdate(this.buildBarDDL()); + this.executeUpdate(this.buildFooDDL()); + this.executeUpdate(this.buildBazDDL()); + this.executeUpdate(this.buildFooBazDDL()); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getSchemaNamed("TABLE_TEST"); + + // FOO + Table fooTable = schema.getTableNamed("FOO"); + assertEquals(3, fooTable.columnsSize()); + assertEquals(1, fooTable.primaryKeyColumnsSize()); + assertEquals(1, fooTable.foreignKeysSize()); + + Column pkColumn = fooTable.getPrimaryKeyColumn(); + assertEquals("ID", pkColumn.getName()); + Column idColumn = fooTable.getColumnNamed("ID"); + assertSame(pkColumn, idColumn); + assertEquals("INTEGER", idColumn.getDataTypeName()); + assertSame(fooTable, idColumn.getTable()); + assertTrue(idColumn.isPrimaryKeyColumn()); + assertFalse(idColumn.isForeignKeyColumn()); + assertEquals("int", idColumn.getJavaTypeDeclaration()); + + Column nameColumn = fooTable.getColumnNamed("NAME"); + assertEquals("VARCHAR", nameColumn.getDataTypeName()); + assertEquals("java.lang.String", nameColumn.getJavaTypeDeclaration()); + assertFalse(nameColumn.isPrimaryKeyColumn()); + + Column barColumn = fooTable.getColumnNamed("BAR_ID"); + assertEquals("INTEGER", barColumn.getDataTypeName()); + assertTrue(barColumn.isForeignKeyColumn()); + assertFalse(barColumn.isPrimaryKeyColumn()); + + ForeignKey barFK = fooTable.foreignKeys().next(); // there should only be 1 foreign key + assertEquals(1, barFK.columnPairsSize()); + assertEquals("BAR", barFK.getAttributeName()); + assertNull(barFK.getJoinColumnAnnotationIdentifier("bar")); + assertEquals("BAR_ID", barFK.getJoinColumnAnnotationIdentifier("primaryBar")); + assertSame(fooTable, barFK.getBaseTable()); + + assertFalse(fooTable.isPossibleJoinTable()); + assertSame(schema, fooTable.getSchema()); + + // BAR + Table barTable = schema.getTableNamed("BAR"); + assertEquals(2, barTable.columnsSize()); + assertEquals(1, barTable.primaryKeyColumnsSize()); + assertEquals(0, barTable.foreignKeysSize()); + assertEquals("ID", barTable.getPrimaryKeyColumn().getName()); + assertFalse(barTable.isPossibleJoinTable()); + assertEquals("BLOB", barTable.getColumnNamed("CHUNK").getDataTypeName()); + assertEquals("byte[]", barTable.getColumnNamed("CHUNK").getJavaTypeDeclaration()); + assertTrue(barTable.getColumnNamed("CHUNK").dataTypeIsLOB()); + assertSame(barTable, barFK.getReferencedTable()); + + // FOO_BAZ + Table foo_bazTable = schema.getTableNamed("FOO_BAZ"); + assertEquals(2, foo_bazTable.columnsSize()); + assertEquals(0, foo_bazTable.primaryKeyColumnsSize()); + assertEquals(2, foo_bazTable.foreignKeysSize()); + assertTrue(foo_bazTable.isPossibleJoinTable()); + assertTrue(foo_bazTable.joinTableNameIsDefault()); + assertTrue(foo_bazTable.getColumnNamed("FOO_ID").isForeignKeyColumn()); + + this.dropTable("TABLE_TEST", "FOO_BAZ"); + this.dropTable("TABLE_TEST", "BAZ"); + this.dropTable("TABLE_TEST", "FOO"); + this.dropTable("TABLE_TEST", "BAR"); + this.dropSchema("TABLE_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ + + private String buildBarDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE BAR (").append(CR); + sb.append(" ID INT PRIMARY KEY,").append(CR); + sb.append(" CHUNK BLOB(100K)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE FOO (").append(CR); + sb.append(" ID INT PRIMARY KEY,").append(CR); + sb.append(" NAME VARCHAR(20),").append(CR); + sb.append(" BAR_ID INT REFERENCES BAR(ID)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE BAZ (").append(CR); + sb.append(" ID INT PRIMARY KEY,").append(CR); + sb.append(" NAME VARCHAR(20)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE FOO_BAZ (").append(CR); + sb.append(" FOO_ID INT REFERENCES FOO(ID),").append(CR); + sb.append(" BAZ_ID INT REFERENCES BAZ(ID)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + public void testColumnLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("TABLE_TEST", "test"); + this.dropSchema("TABLE_TEST"); + + this.executeUpdate("CREATE SCHEMA TABLE_TEST"); + this.executeUpdate("SET SCHEMA = TABLE_TEST"); + + // lowercase + this.executeUpdate("CREATE TABLE test (id INTEGER, name VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Table table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("id")); + assertNotNull(table.getColumnNamed("name")); + + this.dropTable("TABLE_TEST", "test"); + + // uppercase + this.executeUpdate("CREATE TABLE test (ID INTEGER, NAME VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("ID")); + assertNotNull(table.getColumnNamed("NAME")); + + this.dropTable("TABLE_TEST", "test"); + + // mixed case + this.executeUpdate("CREATE TABLE test (Id INTEGER, Name VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("Id")); + assertNotNull(table.getColumnNamed("Name")); + + this.dropTable("TABLE_TEST", "test"); + + // delimited + this.executeUpdate("CREATE TABLE test (\"Id\" INTEGER, \"Name\" VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("\"Id\"")); + assertNotNull(table.getColumnNamed("\"Name\"")); + + this.dropTable("TABLE_TEST", "test"); + this.dropSchema("TABLE_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private void dropTable(String schemaName, String tableName) throws Exception { + Schema schema= this.getSchemaNamed(schemaName); + if (schema != null) { + if (schema.getTableNamed(tableName) != null) { + this.executeUpdate("DROP TABLE " + schemaName + '.' + tableName); + } + } + } + + /** + * NB: A Derby schema must be empty before it can be dropped. + */ + private void dropSchema(String name) throws Exception { + if (this.getSchemaNamed(name) != null) { + this.executeUpdate("DROP SCHEMA " + name + " RESTRICT"); + } + } + +} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQL41Tests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQL41Tests.java deleted file mode 100644 index 37c190f113..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQL41Tests.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * 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.db.tests.internal.platforms; - - -/** - * SQL Server 2005 Driver Test - */ -public class MySQL41Tests extends DTPPlatformTests { - - public MySQL41Tests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "MySql"; - } - - @Override - protected String databaseVersion() { - return "4.1"; - } - - @Override - protected String driverClass() { - return "com.mysql.jdbc.Driver"; - } - - @Override - protected String driverDefinitionId() { - return "DriverDefn.MySQL JDBC Driver"; - } - - @Override - protected String driverDefinitionType() { - return "org.eclipse.datatools.enablement.mysql.4_1.driverTemplate"; - } - - @Override - protected String driverName() { - return "MySQL JDBC Driver"; - } - - @Override - protected String getConfigName() { - return "mysql41.properties"; - } - -}
\ No newline at end of file diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQLTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQLTests.java new file mode 100644 index 0000000000..85e0e36750 --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/MySQLTests.java @@ -0,0 +1,340 @@ +/******************************************************************************* + * 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.db.tests.internal.platforms; + +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; + + +/** + * SQL Server 2005 Driver Test + * + * Notes: + * - We can only get database objects from the database associated with our + * connection profile. + * - We can reference objects across multiple databases, so they are sorta like + * schemas.... + * - Foreign keys must be defined as table-level constraints; they cannot be + * defined as part of the column clause. + * - Case-sensitivity and -folding is whacked on MySQL.... + */ +@SuppressWarnings("nls") +public class MySQLTests extends DTPPlatformTests { + + public MySQLTests( String name) { + super(name); + } + + @Override + protected String getPlatformPropertiesFileName() { + return "mysql.properties"; + } + + @Override + protected String getDriverName() { + return "MySQL JDBC Driver"; + } + + @Override + protected String getDriverDefinitionID() { + return "DriverDefn.MySQL JDBC Driver"; + } + + @Override + protected String getDriverDefinitionType() { + return "org.eclipse.datatools.enablement.mysql.4_1.driverTemplate"; + } + + @Override + protected String getDatabaseVendor() { + return "MySql"; + } + + @Override + protected String getDatabaseVersion() { + return "4.1"; + } + + @Override + protected String getDriverClass() { + return "com.mysql.jdbc.Driver"; + } + + @Override + protected String getDefaultJDBCURL() { + return "jdbc:mysql://localhost:3306"; + } + + @Override + protected String getProfileName() { + return "MySQL_4.1"; + } + + @Override + protected String getProfileDescription() { + return "MySQL 4.1 JDBC Profile [Test]"; + } + + public void testDatabase() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + // MySQL has a single schema with the same name as the database + Schema schema = this.getDatabase().getSchemaNamed(this.getDatabaseName()); + assertNotNull(schema); + assertSame(this.getDatabase().getDefaultSchema(), schema); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testTable() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + +// this.dropDatabase("table_test"); + +// this.executeUpdate("CREATE DATABASE table_test"); + + // we must execute a USE statement before defining our tables + this.executeUpdate("USE " + this.getDatabaseName()); + + this.dropTable(this.getDatabaseName(), "foo_baz"); + this.dropTable(this.getDatabaseName(), "baz"); + this.dropTable(this.getDatabaseName(), "foo"); + this.dropTable(this.getDatabaseName(), "bar"); + + this.executeUpdate(this.buildBarDDL()); + this.executeUpdate(this.buildFooDDL()); + this.executeUpdate(this.buildBazDDL()); + this.executeUpdate(this.buildFooBazDDL()); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getDefaultSchema(); + + // foo + Table fooTable = schema.getTableNamed("foo"); + assertEquals(3, fooTable.columnsSize()); + assertEquals(1, fooTable.primaryKeyColumnsSize()); + assertEquals(1, fooTable.foreignKeysSize()); + + Column pkColumn = fooTable.getPrimaryKeyColumn(); + assertEquals("id", pkColumn.getName()); + Column idColumn = fooTable.getColumnNamed("id"); + assertSame(pkColumn, idColumn); + assertEquals("INT", idColumn.getDataTypeName()); + assertSame(fooTable, idColumn.getTable()); + assertTrue(idColumn.isPrimaryKeyColumn()); + assertFalse(idColumn.isForeignKeyColumn()); + assertEquals("int", idColumn.getJavaTypeDeclaration()); + + Column nameColumn = fooTable.getColumnNamed("name"); + assertEquals("VARCHAR", nameColumn.getDataTypeName()); + assertEquals("java.lang.String", nameColumn.getJavaTypeDeclaration()); + assertFalse(nameColumn.isPrimaryKeyColumn()); + + Column barColumn = fooTable.getColumnNamed("bar_id"); + assertEquals("INT", barColumn.getDataTypeName()); + assertTrue(barColumn.isForeignKeyColumn()); + assertFalse(barColumn.isPrimaryKeyColumn()); + + ForeignKey barFK = fooTable.foreignKeys().next(); // there should only be 1 foreign key + assertEquals(1, barFK.columnPairsSize()); + assertEquals("bar", barFK.getAttributeName()); + assertNull(barFK.getJoinColumnAnnotationIdentifier("bar")); + assertEquals("bar_id", barFK.getJoinColumnAnnotationIdentifier("primaryBar")); + assertSame(fooTable, barFK.getBaseTable()); + + assertFalse(fooTable.isPossibleJoinTable()); + assertSame(schema, fooTable.getSchema()); + + // BAR + Table barTable = schema.getTableNamed("bar"); + assertEquals(2, barTable.columnsSize()); + assertEquals(1, barTable.primaryKeyColumnsSize()); + assertEquals(0, barTable.foreignKeysSize()); + assertEquals("id", barTable.getPrimaryKeyColumn().getName()); + assertFalse(barTable.isPossibleJoinTable()); + assertEquals("BLOB", barTable.getColumnNamed("chunk").getDataTypeName()); + assertEquals("byte[]", barTable.getColumnNamed("chunk").getJavaTypeDeclaration()); + assertTrue(barTable.getColumnNamed("chunk").dataTypeIsLOB()); + assertSame(barTable, barFK.getReferencedTable()); + + // FOO_BAZ + Table foo_bazTable = schema.getTableNamed("foo_baz"); + assertEquals(2, foo_bazTable.columnsSize()); + assertEquals(0, foo_bazTable.primaryKeyColumnsSize()); + assertEquals(2, foo_bazTable.foreignKeysSize()); + assertTrue(foo_bazTable.isPossibleJoinTable()); + assertTrue(foo_bazTable.joinTableNameIsDefault()); + assertTrue(foo_bazTable.getColumnNamed("foo_id").isForeignKeyColumn()); + + this.dropTable(this.getDatabaseName(), "foo_baz"); + this.dropTable(this.getDatabaseName(), "baz"); + this.dropTable(this.getDatabaseName(), "foo"); + this.dropTable(this.getDatabaseName(), "bar"); + +// this.dropDatabase("table_test"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ + + private String buildBarDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE bar (").append(CR); + sb.append(" id INTEGER PRIMARY KEY,").append(CR); + sb.append(" chunk BLOB").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE foo (").append(CR); + sb.append(" id INTEGER PRIMARY KEY,").append(CR); + sb.append(" name VARCHAR(20),").append(CR); + sb.append(" bar_id INTEGER,").append(CR); + sb.append(" FOREIGN KEY (bar_id) REFERENCES bar(id)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE baz (").append(CR); + sb.append(" id INTEGER PRIMARY KEY,").append(CR); + sb.append(" name VARCHAR(20)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE foo_baz (").append(CR); + sb.append(" foo_id INT,").append(CR); + sb.append(" baz_id INT,").append(CR); + sb.append(" FOREIGN KEY (foo_id) REFERENCES foo(id),").append(CR); + sb.append(" FOREIGN KEY (baz_id) REFERENCES baz(id)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + /** + * On Windows, table names get folded to lowercase by default; + * even if the name is delimited (apparently). + */ + public void testTableLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + // we must execute a USE statement before defining our tables + this.executeUpdate("USE " + this.getDatabaseName()); + + this.dropTable(this.getDatabaseName(), "test1"); + this.dropTable(this.getDatabaseName(), "TEST2"); + this.dropTable(this.getDatabaseName(), "`TEST3`"); + + this.executeUpdate("CREATE TABLE test1 (id INTEGER, name VARCHAR(20))"); + this.executeUpdate("CREATE TABLE TEST2 (id INTEGER, name VARCHAR(20))"); + this.executeUpdate("CREATE TABLE `TEST3` (id INTEGER, name VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getDefaultSchema(); + + Table test1Table = schema.getTableNamed("test1"); + assertNotNull(test1Table); + + // this probably only works on Windows + Table test2Table = schema.getTableNamed("test2"); + assertNotNull(test2Table); + + // this probably only works on Windows + Table test3Table = schema.getTableNamed("`test3`"); + assertNotNull(test3Table); + + this.dropTable(this.getDatabaseName(), "test1"); + this.dropTable(this.getDatabaseName(), "TEST2"); + this.dropTable(this.getDatabaseName(), "`TEST3`"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testColumnLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + // we must execute a USE statement before defining our tables + this.executeUpdate("USE " + this.getDatabaseName()); + this.dropTable(this.getDatabaseName(), "test"); + + // lowercase + this.executeUpdate("CREATE TABLE test (id INTEGER, name VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Table table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("id")); + assertNotNull(table.getColumnNamed("name")); + + this.dropTable(this.getDatabaseName(), "test"); + + // uppercase + this.executeUpdate("CREATE TABLE test (ID INTEGER, NAME VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("ID")); + assertNotNull(table.getColumnNamed("NAME")); + + this.dropTable(this.getDatabaseName(), "test"); + + // mixed case + this.executeUpdate("CREATE TABLE test (Id INTEGER, Name VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("Id")); + assertNotNull(table.getColumnNamed("Name")); + + this.dropTable(this.getDatabaseName(), "test"); + + // delimited + this.executeUpdate("CREATE TABLE test (`Id` INTEGER, `Name` VARCHAR(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("`Id`")); + assertNotNull(table.getColumnNamed("`Name`")); + + this.dropTable(this.getDatabaseName(), "test"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private void dropTable(String dbName, String tableName) throws Exception { + this.executeUpdate("DROP TABLE IF EXISTS " + dbName + '.' + tableName); + } + +// private void dropDatabase(String name) throws Exception { +// this.executeUpdate("DROP DATABASE IF EXISTS " + name); +// } +// +} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gTests.java index 4fa85b4db8..e38a46fecc 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gTests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gTests.java @@ -9,49 +9,306 @@ ******************************************************************************/ package org.eclipse.jpt.db.tests.internal.platforms; +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; /** * Oracle 10g Thin Driver Test */ +@SuppressWarnings("nls") public class Oracle10gTests extends DTPPlatformTests { - public Oracle10gTests( String name) { - super( name); - } + public Oracle10gTests( String name) { + super( name); + } + + @Override + protected String getPlatformPropertiesFileName() { + return "oracle10g.properties"; + } + + @Override + protected String getDriverName() { + return "Oracle 10g Thin Driver"; + } - @Override - protected String databaseVendor() { + @Override + protected String getDriverDefinitionID() { + return "DriverDefn.Oracle Thin Driver"; + } + + @Override + protected String getDriverDefinitionType() { + return "org.eclipse.datatools.enablement.oracle.10.driverTemplate"; + } + + @Override + protected String getDatabaseVendor() { return "Oracle"; } - @Override - protected String databaseVersion() { + @Override + protected String getDatabaseVersion() { return "10"; } - @Override - protected String driverClass() { + @Override + protected String getDriverClass() { return "oracle.jdbc.OracleDriver"; } - @Override - protected String driverDefinitionId() { - return "DriverDefn.Oracle Thin Driver"; + @Override + protected String getProfileName() { + return "Oracle10g_10.1.0.4"; } - @Override - protected String driverDefinitionType() { - return "org.eclipse.datatools.enablement.oracle.10.driverTemplate"; + @Override + protected String getProfileDescription() { + return "Oracle10g (10.1.0.4) JDBC Profile [Test]"; } - @Override - protected String driverName() { - return "Oracle 10g Thin Driver"; + @Override + public void testOffline() { + // working offline is pretty ugly + } + + @Override + public void testConnectionListenerOffline() { + // working offline is pretty ugly + } + + public void testDatabase() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + // Oracle should have a schema with the same name as the user + Schema schema = this.getDatabase().getSchemaNamed(this.getUserID()); + assertNotNull(schema); + assertSame(this.getDatabase().getDefaultSchema(), schema); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testTable() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("foo_baz"); + this.dropTable("baz"); + this.dropTable("foo"); + this.dropTable("bar"); + + this.executeUpdate(this.buildBarDDL()); + this.executeUpdate(this.buildFooDDL()); + this.executeUpdate(this.buildBazDDL()); + this.executeUpdate(this.buildFooBazDDL()); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getDefaultSchema(); + + // foo + Table fooTable = schema.getTableNamed("foo"); + assertEquals(3, fooTable.columnsSize()); + assertEquals(1, fooTable.primaryKeyColumnsSize()); + assertEquals(1, fooTable.foreignKeysSize()); + + Column pkColumn = fooTable.getPrimaryKeyColumn(); + assertEquals("ID", pkColumn.getName()); + Column idColumn = fooTable.getColumnNamed("id"); + assertSame(pkColumn, idColumn); + assertEquals("NUMBER", idColumn.getDataTypeName()); + assertSame(fooTable, idColumn.getTable()); + assertTrue(idColumn.isPrimaryKeyColumn()); + assertFalse(idColumn.isForeignKeyColumn()); + assertEquals("java.math.BigDecimal", idColumn.getJavaTypeDeclaration()); + + Column nameColumn = fooTable.getColumnNamed("name"); + assertEquals("VARCHAR2", nameColumn.getDataTypeName()); + assertEquals("java.lang.String", nameColumn.getJavaTypeDeclaration()); + assertFalse(nameColumn.isPrimaryKeyColumn()); + + Column barColumn = fooTable.getColumnNamed("bar_id"); + assertEquals("NUMBER", barColumn.getDataTypeName()); + assertTrue(barColumn.isForeignKeyColumn()); + assertFalse(barColumn.isPrimaryKeyColumn()); + + ForeignKey barFK = fooTable.foreignKeys().next(); // there should only be 1 foreign key + assertEquals(1, barFK.columnPairsSize()); + assertEquals("BAR", barFK.getAttributeName()); + assertNull(barFK.getJoinColumnAnnotationIdentifier("bar")); + assertEquals("BAR_ID", barFK.getJoinColumnAnnotationIdentifier("primaryBar")); + assertSame(fooTable, barFK.getBaseTable()); + + assertFalse(fooTable.isPossibleJoinTable()); + assertSame(schema, fooTable.getSchema()); + + // BAR + Table barTable = schema.getTableNamed("bar"); + assertEquals(2, barTable.columnsSize()); + assertEquals(1, barTable.primaryKeyColumnsSize()); + assertEquals(0, barTable.foreignKeysSize()); + assertEquals("ID", barTable.getPrimaryKeyColumn().getName()); + assertFalse(barTable.isPossibleJoinTable()); + assertEquals("BLOB", barTable.getColumnNamed("chunk").getDataTypeName()); + assertEquals("byte[]", barTable.getColumnNamed("chunk").getJavaTypeDeclaration()); + assertTrue(barTable.getColumnNamed("chunk").dataTypeIsLOB()); + assertSame(barTable, barFK.getReferencedTable()); + + // FOO_BAZ + Table foo_bazTable = schema.getTableNamed("foo_baz"); + assertEquals(2, foo_bazTable.columnsSize()); + assertEquals(0, foo_bazTable.primaryKeyColumnsSize()); + assertEquals(2, foo_bazTable.foreignKeysSize()); + assertTrue(foo_bazTable.isPossibleJoinTable()); + assertTrue(foo_bazTable.joinTableNameIsDefault()); + assertTrue(foo_bazTable.getColumnNamed("foo_id").isForeignKeyColumn()); + + this.dropTable("foo_baz"); + this.dropTable("baz"); + this.dropTable("foo"); + this.dropTable("bar"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ + + private String buildBarDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE bar (").append(CR); + sb.append(" id NUMBER(10) PRIMARY KEY,").append(CR); + sb.append(" chunk BLOB").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE foo (").append(CR); + sb.append(" id NUMBER(10) PRIMARY KEY,").append(CR); + sb.append(" name VARCHAR2(20),").append(CR); + sb.append(" bar_id REFERENCES bar(id)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE baz (").append(CR); + sb.append(" id NUMBER(10) PRIMARY KEY,").append(CR); + sb.append(" name VARCHAR2(20)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE foo_baz (").append(CR); + sb.append(" foo_id NUMBER(10) REFERENCES foo(id),").append(CR); + sb.append(" baz_id NUMBER(10) REFERENCES baz(id)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + public void testTableLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("test1"); + this.dropTable("TEST2"); + this.dropTable("\"test3\""); + + this.executeUpdate("CREATE TABLE test1 (id NUMBER(10), name VARCHAR2(20))"); + this.executeUpdate("CREATE TABLE TEST2 (id NUMBER(10), name VARCHAR2(20))"); + this.executeUpdate("CREATE TABLE \"test3\" (id NUMBER(10), name VARCHAR2(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getDefaultSchema(); + + Table test1Table = schema.getTableNamed("test1"); + assertNotNull(test1Table); + test1Table = schema.getTableNamed("TEST1"); + assertNotNull(test1Table); + + Table test2Table = schema.getTableNamed("test2"); + assertNotNull(test2Table); + test2Table = schema.getTableNamed("TEST2"); + assertNotNull(test2Table); + + Table test3Table = schema.getTableNamed("\"test3\""); + assertNotNull(test3Table); + test3Table = schema.getTableNamed("test3"); + assertNull(test3Table); + + this.dropTable("test1"); + this.dropTable("TEST2"); + this.dropTable("\"test3\""); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testColumnLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("test"); + + // lowercase + this.executeUpdate("CREATE TABLE test (id NUMBER(10), name VARCHAR2(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Table table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("id")); + assertNotNull(table.getColumnNamed("name")); + + this.dropTable("test"); + + // uppercase + this.executeUpdate("CREATE TABLE test (ID NUMBER(10), NAME VARCHAR2(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("ID")); + assertNotNull(table.getColumnNamed("NAME")); + + this.dropTable("test"); + + // mixed case + this.executeUpdate("CREATE TABLE test (Id NUMBER(10), Name VARCHAR2(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("Id")); + assertNotNull(table.getColumnNamed("Name")); + + this.dropTable("test"); + + // delimited + this.executeUpdate("CREATE TABLE test (\"Id\" NUMBER(10), \"Name\" VARCHAR2(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getDefaultSchema().getTableNamed("test"); + assertNotNull(table.getColumnNamed("\"Id\"")); + assertNotNull(table.getColumnNamed("\"Name\"")); + + this.dropTable("test"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private void dropTable(String tableName) throws Exception { + this.executeUpdateIgnoreErrors("DROP TABLE " + tableName + " CASCADE CONSTRAINTS"); } - - @Override - protected String getConfigName() { - return "oracle10g.properties"; - } } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gXETests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gXETests.java index 78e0548b1b..3ffb7dbc77 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gXETests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle10gXETests.java @@ -13,45 +13,56 @@ package org.eclipse.jpt.db.tests.internal.platforms; /** * Oracle 10g Thin Driver Test */ +@SuppressWarnings("nls") public class Oracle10gXETests extends DTPPlatformTests { - public Oracle10gXETests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "Oracle"; + public Oracle10gXETests( String name) { + super( name); } - @Override - protected String databaseVersion() { - return "10"; + @Override + protected String getPlatformPropertiesFileName() { + return "oracle10gXE.properties"; } - @Override - protected String driverClass() { - return "oracle.jdbc.OracleDriver"; + @Override + protected String getDriverName() { + return "Oracle 10g Thin Driver"; } - @Override - protected String driverDefinitionId() { + @Override + protected String getDriverDefinitionID() { return "DriverDefn.Oracle Thin Driver"; } - @Override - protected String driverDefinitionType() { + @Override + protected String getDriverDefinitionType() { return "org.eclipse.datatools.enablement.oracle.10.driverTemplate"; } - @Override - protected String driverName() { - return "Oracle 10g Thin Driver"; + @Override + protected String getDatabaseVendor() { + return "Oracle"; + } + + @Override + protected String getDatabaseVersion() { + return "10"; + } + + @Override + protected String getDriverClass() { + return "oracle.jdbc.OracleDriver"; + } + + @Override + protected String getProfileName() { + return "Oracle10g_XE"; + } + + @Override + protected String getProfileDescription() { + return "Oracle10g XE Release 2 (10.2) JDBC Profile [Test]"; } - - @Override - protected String getConfigName() { - return "oracle10gXE.properties"; - } } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle9iTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle9iTests.java index 8e1795dc24..8efa20bd80 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle9iTests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Oracle9iTests.java @@ -13,45 +13,56 @@ package org.eclipse.jpt.db.tests.internal.platforms; /** * Oracle 9i Thin Driver Test */ +@SuppressWarnings("nls") public class Oracle9iTests extends DTPPlatformTests { - public Oracle9iTests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "Oracle"; + public Oracle9iTests( String name) { + super( name); } - @Override - protected String databaseVersion() { - return "9"; + @Override + protected String getPlatformPropertiesFileName() { + return "oracle9i.properties"; } - @Override - protected String driverClass() { - return "oracle.jdbc.OracleDriver"; + @Override + protected String getDriverName() { + return "Oracle 9i Thin Driver"; } - @Override - protected String driverDefinitionId() { + @Override + protected String getDriverDefinitionID() { return "DriverDefn.Oracle Thin Driver"; } - @Override - protected String driverDefinitionType() { + @Override + protected String getDriverDefinitionType() { return "org.eclipse.datatools.enablement.oracle.9.driverTemplate"; } - @Override - protected String driverName() { - return "Oracle 9i Thin Driver"; + @Override + protected String getDatabaseVendor() { + return "Oracle"; + } + + @Override + protected String getDatabaseVersion() { + return "9"; + } + + @Override + protected String getDriverClass() { + return "oracle.jdbc.OracleDriver"; + } + + @Override + protected String getProfileName() { + return "Oracle9i"; + } + + @Override + protected String getProfileDescription() { + return "Oracle9i JDBC Profile [Test]"; } - - @Override - protected String getConfigName() { - return "oracle9i.properties"; - } } diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQL824Tests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQL824Tests.java deleted file mode 100644 index 8e011ad987..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQL824Tests.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************* - * 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.db.tests.internal.platforms; - - -/** - * Oracle 10g Thin Driver Test - */ -public class PostgreSQL824Tests extends DTPPlatformTests { - - public PostgreSQL824Tests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "postgres"; - } - - @Override - protected String databaseVersion() { - return "8.x"; - } - - @Override - protected String driverClass() { - return "org.postgresql.Driver"; - } - - @Override - protected String driverDefinitionId() { - return "DriverDefn.PostgreSQL JDBC Driver"; - } - - @Override - protected String driverDefinitionType() { - return "org.eclipse.datatools.enablement.postgresql.postgresqlDriverTemplate"; - } - - @Override - protected String driverName() { - return "PostgreSQL JDBC Driver"; - } - - @Override - protected String getConfigName() { - return "postgresql824.properties"; - } - -} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQLTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQLTests.java new file mode 100644 index 0000000000..6f32c77daa --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/PostgreSQLTests.java @@ -0,0 +1,424 @@ +/******************************************************************************* + * 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.db.tests.internal.platforms; + +import org.eclipse.datatools.connectivity.sqm.core.rte.ICatalogObject; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.ForeignKey; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; + + +/** + * Oracle 10g Thin Driver Test + */ +@SuppressWarnings("nls") +public class PostgreSQLTests extends DTPPlatformTests { + + public PostgreSQLTests( String name) { + super( name); + } + + @Override + protected String getPlatformPropertiesFileName() { + return "postgresql.properties"; + } + + @Override + protected String getDriverName() { + return "PostgreSQL JDBC Driver"; + } + + @Override + protected String getDriverDefinitionID() { + return "DriverDefn.PostgreSQL JDBC Driver"; + } + + @Override + protected String getDriverDefinitionType() { + return "org.eclipse.datatools.enablement.postgresql.postgresqlDriverTemplate"; + } + + @Override + protected String getDatabaseVendor() { + return "postgres"; + } + + @Override + protected String getDatabaseVersion() { + return "8.x"; + } + + @Override + protected String getDriverClass() { + return "org.postgresql.Driver"; + } + + @Override + protected String getDefaultJDBCURL() { + return "jdbc:postgresql"; + } + + @Override + protected String getProfileName() { + return "PostgreSQL"; + } + + @Override + protected String getProfileDescription() { + return "PostgreSQL 8.2 JDBC Profile [Test]"; + } + + @Override + public void testOffline() { + // DTP does not support PostgreSQL off-line - see 226704/241558 + } + + @Override + public void testConnectionListenerOffline() { + // DTP does not support PostgreSQL off-line - see 226704/241558 + } + + public void testSchema() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("TEST1"); + this.dropSchema("TEST2"); + + this.executeUpdate("CREATE SCHEMA TEST1"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema1 = this.getDatabase().getSchemaNamed("TEST1"); + assertNotNull(schema1); + + this.executeUpdate("CREATE SCHEMA TEST2"); + Schema schema2 = this.getDatabase().getSchemaNamed("TEST2"); + assertNull(schema2); // should be null until refresh + + ((ICatalogObject) this.getDTPDatabase()).refresh(); + assertSame(this.getDatabase(), listener.changedDatabase); + + schema2 = this.getDatabase().getSchemaNamed("TEST2"); + assertNotNull(schema2); + assertNotSame(schema1, this.getDatabase().getSchemaNamed("TEST1")); // we should have a new schema after the refresh + + this.dropSchema("TEST2"); + this.dropSchema("TEST1"); + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testSchemaLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("LOOKUP_TEST"); + this.dropSchema("\"lookup_TEST\""); + + this.executeUpdate("CREATE SCHEMA LOOKUP_TEST"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + assertNotNull(this.getDatabase().getSchemaNamed("LOOKUP_TEST")); + assertNotNull(this.getDatabase().getSchemaNamed("lookup_test")); + assertNotNull(this.getDatabase().getSchemaNamed("lookup_TEST")); + assertNotNull(this.getDatabase().getSchemaNamed("\"lookup_test\"")); + assertNull(this.getDatabase().getSchemaNamed("\"lookup_TEST\"")); + assertNull(this.getDatabase().getSchemaNamed("\"LOOKUP_TEST\"")); + + this.dropSchema("LOOKUP_TEST"); + + this.executeUpdate("CREATE SCHEMA \"lookup_TEST\""); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + assertNull(this.getDatabase().getSchemaNamed("LOOKUP_TEST")); + assertNull(this.getDatabase().getSchemaNamed("lookup_test")); + assertNull(this.getDatabase().getSchemaNamed("lookup_TEST")); + assertNull(this.getDatabase().getSchemaNamed("\"LOOKUP_TEST\"")); + assertNotNull(this.getDatabase().getSchemaNamed("\"lookup_TEST\"")); + + this.dropSchema("\"lookup_TEST\""); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testSchemaAnnotationIdentifier() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropSchema("LOOKUP_TEST"); + this.dropSchema("\"lookup_TEST\""); + + this.executeUpdate("CREATE SCHEMA lookup_test"); // this gets folded to uppercase + this.executeUpdate("CREATE SCHEMA \"lookup_TEST\""); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getSchemaNamed("LOOKUP_TEST"); + assertEquals("lookup_test", schema.getAnnotationIdentifier()); + assertEquals("lookup_test", schema.getAnnotationIdentifier("LookupTest")); + assertNull(schema.getAnnotationIdentifier("Lookup_Test")); + + schema = this.getDatabase().getSchemaNamed("lookup_test"); + assertEquals("lookup_test", schema.getAnnotationIdentifier()); + + schema = this.getDatabase().getSchemaNamed("\"lookup_TEST\""); + assertEquals("\"lookup_TEST\"", schema.getAnnotationIdentifier()); + assertEquals("\"lookup_TEST\"", schema.getAnnotationIdentifier("lookup_TEST")); + + this.dropSchema("\"lookup_TEST\""); + this.dropSchema("LOOKUP_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + public void testTable() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("TABLE_TEST", "FOO_BAZ"); + this.dropTable("TABLE_TEST", "BAZ"); + this.dropTable("TABLE_TEST", "FOO"); + this.dropTable("TABLE_TEST", "BAR"); + this.dropSchema("TABLE_TEST"); + + this.executeUpdate("CREATE SCHEMA TABLE_TEST"); + this.executeUpdate("SET search_path TO TABLE_TEST"); + + this.executeUpdate(this.buildBarDDL()); + this.executeUpdate(this.buildFooDDL()); + this.executeUpdate(this.buildBazDDL()); + this.executeUpdate(this.buildFooBazDDL()); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Schema schema = this.getDatabase().getSchemaNamed("TABLE_TEST"); + + // FOO + Table fooTable = schema.getTableNamed("FOO"); + assertEquals(3, fooTable.columnsSize()); + assertEquals(1, fooTable.primaryKeyColumnsSize()); + assertEquals(1, fooTable.foreignKeysSize()); + + Column pkColumn = fooTable.getPrimaryKeyColumn(); + assertEquals("id", pkColumn.getName()); + Column idColumn = fooTable.getColumnNamed("ID"); + assertSame(pkColumn, idColumn); + assertEquals("INT4", idColumn.getDataTypeName()); + assertSame(fooTable, idColumn.getTable()); + assertTrue(idColumn.isPrimaryKeyColumn()); + assertFalse(idColumn.isForeignKeyColumn()); + assertEquals("java.lang.Integer", idColumn.getJavaTypeDeclaration()); + + Column nameColumn = fooTable.getColumnNamed("NAME"); + assertEquals("VARCHAR", nameColumn.getDataTypeName()); + assertEquals("java.lang.String", nameColumn.getJavaTypeDeclaration()); + assertFalse(nameColumn.isPrimaryKeyColumn()); + + Column barColumn = fooTable.getColumnNamed("BAR_ID"); + assertEquals("INT4", barColumn.getDataTypeName()); + assertTrue(barColumn.isForeignKeyColumn()); + assertFalse(barColumn.isPrimaryKeyColumn()); + + ForeignKey barFK = fooTable.foreignKeys().next(); // there should only be 1 foreign key + assertEquals(1, barFK.columnPairsSize()); + assertEquals("bar", barFK.getAttributeName()); + assertNull(barFK.getJoinColumnAnnotationIdentifier("bar")); + assertEquals("bar_id", barFK.getJoinColumnAnnotationIdentifier("primaryBar")); + assertSame(fooTable, barFK.getBaseTable()); + + assertFalse(fooTable.isPossibleJoinTable()); + assertSame(schema, fooTable.getSchema()); + + // BAR + Table barTable = schema.getTableNamed("BAR"); + assertEquals(2, barTable.columnsSize()); + assertEquals(1, barTable.primaryKeyColumnsSize()); + assertEquals(0, barTable.foreignKeysSize()); + assertEquals("id", barTable.getPrimaryKeyColumn().getName()); + assertFalse(barTable.isPossibleJoinTable()); + assertEquals("BYTEA", barTable.getColumnNamed("CHUNK").getDataTypeName()); + assertEquals("byte[]", barTable.getColumnNamed("CHUNK").getJavaTypeDeclaration()); + // assertTrue(barTable.getColumnNamed("CHUNK").dataTypeIsLOB()); + assertSame(barTable, barFK.getReferencedTable()); + + // FOO_BAZ + Table foo_bazTable = schema.getTableNamed("FOO_BAZ"); + assertEquals(2, foo_bazTable.columnsSize()); + assertEquals(0, foo_bazTable.primaryKeyColumnsSize()); + assertEquals(2, foo_bazTable.foreignKeysSize()); + assertTrue(foo_bazTable.isPossibleJoinTable()); + assertTrue(foo_bazTable.joinTableNameIsDefault()); + assertTrue(foo_bazTable.getColumnNamed("FOO_ID").isForeignKeyColumn()); + + this.dropTable("TABLE_TEST", "FOO_BAZ"); + this.dropTable("TABLE_TEST", "BAZ"); + this.dropTable("TABLE_TEST", "FOO"); + this.dropTable("TABLE_TEST", "BAR"); + this.dropSchema("TABLE_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private static final String CR = System.getProperty("line.separator"); //$NON-NLS-1$ + + private String buildBarDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE BAR (").append(CR); + sb.append(" ID integer PRIMARY KEY,").append(CR); + sb.append(" CHUNK bytea").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE FOO (").append(CR); + sb.append(" ID integer PRIMARY KEY,").append(CR); + sb.append(" NAME varchar(20),").append(CR); + sb.append(" BAR_ID integer REFERENCES BAR(ID)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE BAZ (").append(CR); + sb.append(" ID integer PRIMARY KEY,").append(CR); + sb.append(" NAME varchar(20)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + private String buildFooBazDDL() { + StringBuilder sb = new StringBuilder(200); + sb.append("CREATE TABLE FOO_BAZ (").append(CR); + sb.append(" FOO_ID int REFERENCES FOO(ID),").append(CR); + sb.append(" BAZ_ID int REFERENCES BAZ(ID)").append(CR); + sb.append(")").append(CR); + return sb.toString(); + } + + public void testColumnLookup() throws Exception { + this.connectionProfile.connect(); + TestConnectionListener listener = new TestConnectionListener(); + this.connectionProfile.addConnectionListener(listener); + + this.dropTable("TABLE_TEST", "test"); + this.dropSchema("TABLE_TEST"); + + this.executeUpdate("CREATE SCHEMA TABLE_TEST"); + this.executeUpdate("SET search_path TO TABLE_TEST"); + + // lowercase + this.executeUpdate("CREATE TABLE test (id int, name varchar(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + Table table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("id")); + assertNotNull(table.getColumnNamed("name")); + + this.dropTable("TABLE_TEST", "test"); + + // uppercase + this.executeUpdate("CREATE TABLE test (ID int, NAME varchar(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("ID")); + assertNotNull(table.getColumnNamed("NAME")); + + this.dropTable("TABLE_TEST", "test"); + + // mixed case + this.executeUpdate("CREATE TABLE test (Id int, Name varchar(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("Id")); + assertNotNull(table.getColumnNamed("Name")); + + this.dropTable("TABLE_TEST", "test"); + + // delimited + this.executeUpdate("CREATE TABLE test (\"Id\" int, \"Name\" varchar(20))"); + ((ICatalogObject) this.getDTPDatabase()).refresh(); + + table = this.getDatabase().getSchemaNamed("TABLE_TEST").getTableNamed("test"); + assertNotNull(table.getColumnNamed("\"Id\"")); + assertNotNull(table.getColumnNamed("\"Name\"")); + + this.dropTable("TABLE_TEST", "test"); + this.dropSchema("TABLE_TEST"); + + this.connectionProfile.removeConnectionListener(listener); + this.connectionProfile.disconnect(); + } + + private void dropTable(String schemaName, String tableName) throws Exception { + Schema schema= this.getSchemaNamed(schemaName); + if (schema != null) { + if (schema.getTableNamed(tableName) != null) { + this.executeUpdate("DROP TABLE " + schemaName + '.' + tableName); + } + } + } + + private void dropSchema(String name) throws Exception { + if (this.getSchemaNamed(name) != null) { + this.executeUpdate("DROP SCHEMA " + name + " CASCADE"); + } + } + +// see 241578/241557 +// public void testSequence() throws Exception { +// this.connectionProfile.connect(); +// TestConnectionListener listener = new TestConnectionListener(); +// this.connectionProfile.addConnectionListener(listener); +// +// this.dropSequence("SEQUENCE_TEST", "FOO"); +// this.dropSchema("SEQUENCE_TEST"); +// +// this.executeUpdate("CREATE SCHEMA SEQUENCE_TEST"); +// this.executeUpdate("SET search_path TO SEQUENCE_TEST"); +// +// this.executeUpdate(this.buildBarDDL()); +// this.executeUpdate("CREATE SEQUENCE FOO START 1"); +//// List<Object[]> list = this.execute("SELECT nextval('foo')"); +//// System.out.println(list); +// ((ICatalogObject) this.getDTPDatabase()).refresh(); +// +// Schema schema = this.getDatabase().getSchemaNamed("SEQUENCE_TEST"); +// Sequence sequence = schema.getSequenceNamed("FOO"); +// assertNotNull(sequence); +// assertEquals("foo_seq", sequence.getName()); +// +// this.dropSequence("SEQUENCE_TEST", "FOO"); +// this.dropSchema("SEQUENCE_TEST"); +// +// this.connectionProfile.removeConnectionListener(listener); +// this.connectionProfile.disconnect(); +// } +// +// private void dropSequence(String schemaName, String sequenceName) throws Exception { +// Schema schema= this.getSchemaNamed(schemaName); +// if (schema != null) { +// if (schema.getSequenceNamed(sequenceName) != null) { +// this.executeUpdate("DROP SEQUENCE " + schemaName + '.' + sequenceName); +// } +// } +// } +// +} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServer2005Tests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServer2005Tests.java deleted file mode 100644 index 350d844d56..0000000000 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServer2005Tests.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * 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.db.tests.internal.platforms; - - -/** - * SQL Server 2005 Driver Test - */ -public class SQLServer2005Tests extends DTPPlatformTests { - - public SQLServer2005Tests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "SQLServer"; - } - - @Override - protected String databaseVersion() { - return "2005"; - } - - @Override - protected String providerId() { - return "org.eclipse.datatools.connectivity.db.generic.connectionProfile"; - } - - @Override - protected String driverName() { - return "Microsoft SQL Server 2005 JDBC Driver"; - } - - @Override - protected String driverDefinitionType() { - return "org.eclipse.datatools.enablement.msft.sqlserver.2005.driverTemplate"; - } - - @Override - protected String driverDefinitionId() { - return "DriverDefn.Microsoft SQL Server 2005 JDBC Driver"; - } - - @Override - protected String driverClass() { - return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - } - - @Override - protected String getConfigName() { - return "sqlserver2005.properties"; - } - -} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServerTests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServerTests.java new file mode 100644 index 0000000000..16603b3343 --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SQLServerTests.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.db.tests.internal.platforms; + + +/** + * SQL Server 2005 Driver Test + */ +@SuppressWarnings("nls") +public class SQLServerTests extends DTPPlatformTests { + + public SQLServerTests( String name) { + super( name); + } + + @Override + protected String getPlatformPropertiesFileName() { + return "sqlserver.properties"; + } + + @Override + protected String getDriverName() { + return "Microsoft SQL Server 2005 JDBC Driver"; + } + + @Override + protected String getDriverDefinitionID() { + return "DriverDefn.Microsoft SQL Server 2005 JDBC Driver"; + } + + @Override + protected String getDriverDefinitionType() { + return "org.eclipse.datatools.enablement.msft.sqlserver.2005.driverTemplate"; + } + + @Override + protected String getDatabaseVendor() { + return "SQLServer"; + } + + @Override + protected String getDatabaseVersion() { + return "2005"; + } + + @Override + protected String getDriverClass() { + return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + } + + @Override + protected String getProfileName() { + return "SQLServer_2005"; + } + + @Override + protected String getProfileDescription() { + return "Microsoft SQL Server 2005 JDBC Profile [Test]"; + } + + @Override + protected String getProviderID() { + return "org.eclipse.datatools.connectivity.db.generic.connectionProfile"; + } + +} diff --git a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Sybase12Tests.java b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SybaseTests.java index c6c7eb3e89..fc16e2ca9a 100644 --- a/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/Sybase12Tests.java +++ b/jpa/tests/org.eclipse.jpt.db.tests/src/org/eclipse/jpt/db/tests/internal/platforms/SybaseTests.java @@ -13,45 +13,56 @@ package org.eclipse.jpt.db.tests.internal.platforms; /** * Oracle 10g Thin Driver Test */ -public class Sybase12Tests extends DTPPlatformTests { +@SuppressWarnings("nls") +public class SybaseTests extends DTPPlatformTests { - public Sybase12Tests( String name) { - super( name); - } - - @Override - protected String databaseVendor() { - return "Sybase"; + public SybaseTests( String name) { + super( name); } - @Override - protected String databaseVersion() { - return "12.x"; + @Override + protected String getPlatformPropertiesFileName() { + return "sybase.properties"; } - @Override - protected String driverClass() { - return "com.sybase.jdbc3.jdbc.SybDriver"; + @Override + protected String getDriverName() { + return "Sybase JDBC Driver"; } - @Override - protected String driverDefinitionId() { + @Override + protected String getDriverDefinitionID() { return "DriverDefn.Sybase JDBC Driver"; } - @Override - protected String driverDefinitionType() { + @Override + protected String getDriverDefinitionType() { return "org.eclipse.datatools.enablement.sybase.ase.12_x.driverTemplate"; } - @Override - protected String driverName() { - return "Sybase JDBC Driver"; + @Override + protected String getDatabaseVendor() { + return "Sybase"; + } + + @Override + protected String getDatabaseVersion() { + return "12.x"; + } + + @Override + protected String getDriverClass() { + return "com.sybase.jdbc3.jdbc.SybDriver"; + } + + @Override + protected String getProfileName() { + return "Sybase_12"; + } + + @Override + protected String getProfileDescription() { + return "Sybase 12 jConnect JDBC Profile [Test]"; } - - @Override - protected String getConfigName() { - return "sybase12.properties"; - } } diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/BooleanHolderTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/BooleanHolderTests.java new file mode 100644 index 0000000000..3e4f266c27 --- /dev/null +++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/BooleanHolderTests.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * 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.utility.tests.internal; + +import org.eclipse.jpt.utility.internal.BooleanHolder; + +import junit.framework.TestCase; + +public class BooleanHolderTests extends TestCase { + + public BooleanHolderTests(String name) { + super(name); + } + + public void testGetValue() { + BooleanHolder bh = new BooleanHolder(true); + assertTrue(bh.getValue()); + } + + public void testIsTrue() { + BooleanHolder bh = new BooleanHolder(true); + assertTrue(bh.isTrue()); + } + + public void testIsFalse() { + BooleanHolder bh = new BooleanHolder(true); + assertFalse(bh.isFalse()); + } + + public void testIs() { + BooleanHolder bh = new BooleanHolder(true); + assertTrue(bh.is(true)); + assertFalse(bh.is(false)); + } + + public void testSetValue() { + BooleanHolder bh = new BooleanHolder(true); + assertTrue(bh.getValue()); + bh.setValue(false); + assertFalse(bh.getValue()); + } + + public void testSetTrue() { + BooleanHolder bh = new BooleanHolder(false); + assertFalse(bh.getValue()); + bh.setTrue(); + assertTrue(bh.getValue()); + } + + + public void testSetFalse() { + BooleanHolder bh = new BooleanHolder(true); + assertTrue(bh.getValue()); + bh.setFalse(); + assertFalse(bh.getValue()); + } + + public void testClone() { + BooleanHolder bh = new BooleanHolder(true); + BooleanHolder clone = (BooleanHolder) bh.clone(); + assertTrue(clone.getValue()); + assertEquals(bh, clone); + } + + public void testEquals() { + BooleanHolder bh1 = new BooleanHolder(true); + BooleanHolder bh2 = new BooleanHolder(true); + assertEquals(bh1, bh2); + + BooleanHolder bh3 = new BooleanHolder(false); + assertFalse(bh1.equals(bh3)); + } + +} diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/JptUtilityTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/JptUtilityTests.java index ae844ed0af..bc306c0ef7 100644 --- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/JptUtilityTests.java +++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/JptUtilityTests.java @@ -29,6 +29,7 @@ public class JptUtilityTests { suite.addTest(JptUtilityNodeTests.suite()); suite.addTestSuite(BitToolsTests.class); + suite.addTestSuite(BooleanHolderTests.class); suite.addTestSuite(ClasspathTests.class); suite.addTestSuite(ClassToolsTests.class); suite.addTestSuite(CollectionToolsTests.class); @@ -42,6 +43,7 @@ public class JptUtilityTests { suite.addTestSuite(JDBCTypeTests.class); suite.addTestSuite(MethodSignatureTests.class); suite.addTestSuite(NameToolsTests.class); + suite.addTestSuite(RangeTests.class); suite.addTestSuite(ReverseComparatorTests.class); suite.addTestSuite(SimpleAssociationTests.class); suite.addTestSuite(SimpleStackTests.class); diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/NameToolsTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/NameToolsTests.java index eb178f211a..a389583e0d 100644 --- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/NameToolsTests.java +++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/NameToolsTests.java @@ -16,6 +16,7 @@ import junit.framework.TestCase; import org.eclipse.jpt.utility.internal.CollectionTools; import org.eclipse.jpt.utility.internal.NameTools; +@SuppressWarnings("nls") public class NameToolsTests extends TestCase { public NameToolsTests(String name) { @@ -146,17 +147,6 @@ public class NameToolsTests extends TestCase { assertEquals("Oracle3", NameTools.uniqueNameFor("Oracle", strings.iterator())); } - public void testUniqueJavaNameForCollection() { - Collection<String> strings = new ArrayList<String>(); - strings.add("Oracle"); - strings.add("Oracle"); - strings.add("Oracle2"); - strings.add("Oracle1"); - - assertEquals("private2", NameTools.uniqueJavaNameFor("private", strings.iterator())); - assertEquals("class2", NameTools.uniqueJavaNameFor("class", strings.iterator())); - } - public void testBuildQualifiedDatabaseObjectName() { assertEquals("catalog.schema.name", NameTools.buildQualifiedDatabaseObjectName("catalog", "schema", "name")); assertEquals("catalog..name", NameTools.buildQualifiedDatabaseObjectName("catalog", null, "name")); @@ -224,4 +214,13 @@ public class NameToolsTests extends TestCase { } + public void testStringIsLegalJavaIdentifier() { + assertFalse(NameTools.stringIsLegalJavaIdentifier("class")); + assertTrue(NameTools.stringIsLegalJavaIdentifier("clasS")); + + assertFalse(NameTools.stringIsLegalJavaIdentifier("7foo")); + assertFalse(NameTools.stringIsLegalJavaIdentifier("foo@bar")); + assertTrue(NameTools.stringIsLegalJavaIdentifier("_foo")); + } + } diff --git a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/StringToolsTests.java b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/StringToolsTests.java index 42f6936eb1..2f85b17ace 100644 --- a/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/StringToolsTests.java +++ b/jpa/tests/org.eclipse.jpt.utility.tests/src/org/eclipse/jpt/utility/tests/internal/StringToolsTests.java @@ -11,15 +11,21 @@ package org.eclipse.jpt.utility.tests.internal; import java.io.StringWriter; import java.io.Writer; + import junit.framework.TestCase; import org.eclipse.jpt.utility.internal.StringTools; +@SuppressWarnings("nls") public class StringToolsTests extends TestCase { public StringToolsTests(String name) { super(name); } + private static void assertEquals(String expected, char[] actual) { + assertEquals(expected, new String(actual)); + } + // ********** padding/truncating ********** public void testPad() { @@ -35,11 +41,11 @@ public class StringToolsTests extends TestCase { } public void testPadCharArray() { - assertEquals("fred", new String(StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 4))); - assertEquals("fred ", new String(StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 6))); + assertEquals("fred", StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 4)); + assertEquals("fred ", StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 6)); boolean exThrown = false; try { - assertEquals("fr", new String(StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 2))); + assertEquals("fr", StringTools.pad(new char[] { 'f', 'r', 'e', 'd' }, 2)); } catch (IllegalArgumentException ex) { exThrown = true; } @@ -116,9 +122,9 @@ public class StringToolsTests extends TestCase { } public void testPadOrTruncateCharArray() { - assertEquals("fred", new String(StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 4))); - assertEquals("fred ", new String(StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 6))); - assertEquals("fr", new String(StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 2))); + assertEquals("fred", StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 4)); + assertEquals("fred ", StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 6)); + assertEquals("fr", StringTools.padOrTruncate(new char[] { 'f', 'r', 'e', 'd' }, 2)); } public void testPadOrTruncateOnWriter() { @@ -170,11 +176,11 @@ public class StringToolsTests extends TestCase { } public void testZeroPadCharArray() { - assertEquals("1234", new String(StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 4))); - assertEquals("001234", new String(StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 6))); + assertEquals("1234", StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 4)); + assertEquals("001234", StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 6)); boolean exThrown = false; try { - assertEquals("12", new String(StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 2))); + assertEquals("12", StringTools.zeroPad(new char[] { '1', '2', '3', '4' }, 2)); } catch (IllegalArgumentException ex) { exThrown = true; } @@ -251,9 +257,9 @@ public class StringToolsTests extends TestCase { } public void testZeroPadOrTruncateCharArray() { - assertEquals("1234", new String(StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 4))); - assertEquals("001234", new String(StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 6))); - assertEquals("34", new String(StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 2))); + assertEquals("1234", StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 4)); + assertEquals("001234", StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 6)); + assertEquals("34", StringTools.zeroPadOrTruncate(new char[] { '1', '2', '3', '4' }, 2)); } public void testZeroPadOrTruncateOnWriter() { @@ -409,7 +415,7 @@ public class StringToolsTests extends TestCase { } private void verifyRemoveFirstOccurrenceCharArray(String string, char charToRemove, String expectedString) { - assertEquals(expectedString, new String(StringTools.removeFirstOccurrence(string.toCharArray(), charToRemove))); + assertEquals(expectedString, StringTools.removeFirstOccurrence(string.toCharArray(), charToRemove)); } public void testRemoveFirstOccurrenceOnWriter() { @@ -473,7 +479,7 @@ public class StringToolsTests extends TestCase { } private void verifyRemoveAllOccurrencesCharArray(String string, char charToRemove, String expectedString) { - assertEquals(expectedString, new String(StringTools.removeAllOccurrences(string.toCharArray(), charToRemove))); + assertEquals(expectedString, StringTools.removeAllOccurrences(string.toCharArray(), charToRemove)); } public void testRemoveAllOccurrencesOnWriter() { @@ -516,61 +522,61 @@ public class StringToolsTests extends TestCase { } public void testRemoveAllWhitespace() { - this.verifyRemoveAllWhitespace("Employee Fred\t", ' ', "EmployeeFred"); - this.verifyRemoveAllWhitespace("\tEmployee\n", ' ', "Employee"); - this.verifyRemoveAllWhitespace("Employee \t Foo", ' ', "EmployeeFoo"); - this.verifyRemoveAllWhitespace(" Emp\tloyee \n Foo", ' ', "EmployeeFoo"); + this.verifyRemoveAllWhitespace("Employee Fred\t", "EmployeeFred"); + this.verifyRemoveAllWhitespace("\tEmployee\n", "Employee"); + this.verifyRemoveAllWhitespace("Employee \t Foo", "EmployeeFoo"); + this.verifyRemoveAllWhitespace(" Emp\tloyee \n Foo", "EmployeeFoo"); } - private void verifyRemoveAllWhitespace(String string, char charToRemove, String expectedString) { + private void verifyRemoveAllWhitespace(String string, String expectedString) { assertEquals(expectedString, StringTools.removeAllWhitespace(string)); } public void testRemoveAllWhitespaceCharArray() { - this.verifyRemoveAllWhitespaceCharArray("Employee Fred\t", ' ', "EmployeeFred"); - this.verifyRemoveAllWhitespaceCharArray("\tEmployee\n", ' ', "Employee"); - this.verifyRemoveAllWhitespaceCharArray("Employee \t Foo", ' ', "EmployeeFoo"); - this.verifyRemoveAllWhitespaceCharArray(" Emp\tloyee \n Foo", ' ', "EmployeeFoo"); + this.verifyRemoveAllWhitespaceCharArray("Employee Fred\t", "EmployeeFred"); + this.verifyRemoveAllWhitespaceCharArray("\tEmployee\n", "Employee"); + this.verifyRemoveAllWhitespaceCharArray("Employee \t Foo", "EmployeeFoo"); + this.verifyRemoveAllWhitespaceCharArray(" Emp\tloyee \n Foo", "EmployeeFoo"); } - private void verifyRemoveAllWhitespaceCharArray(String string, char charToRemove, String expectedString) { - assertEquals(expectedString, new String(StringTools.removeAllWhitespace(string.toCharArray()))); + private void verifyRemoveAllWhitespaceCharArray(String string, String expectedString) { + assertEquals(expectedString, StringTools.removeAllWhitespace(string.toCharArray())); } public void testRemoveAllWhitespaceOnWriter() { - this.verifyRemoveAllWhitespaceOnWriter("Employee Fred\t", ' ', "EmployeeFred"); - this.verifyRemoveAllWhitespaceOnWriter("\tEmployee\n", ' ', "Employee"); - this.verifyRemoveAllWhitespaceOnWriter("Employee \t Foo", ' ', "EmployeeFoo"); - this.verifyRemoveAllWhitespaceOnWriter(" Emp\tloyee \n Foo", ' ', "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnWriter("Employee Fred\t", "EmployeeFred"); + this.verifyRemoveAllWhitespaceOnWriter("\tEmployee\n", "Employee"); + this.verifyRemoveAllWhitespaceOnWriter("Employee \t Foo", "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnWriter(" Emp\tloyee \n Foo", "EmployeeFoo"); } - private void verifyRemoveAllWhitespaceOnWriter(String string, char charToRemove, String expectedString) { + private void verifyRemoveAllWhitespaceOnWriter(String string, String expectedString) { Writer writer = new StringWriter(); StringTools.removeAllWhitespaceOn(string, writer); assertEquals(expectedString, writer.toString()); } public void testRemoveAllWhitespaceOnStringBuffer() { - this.verifyRemoveAllWhitespaceOnStringBuffer("Employee Fred\t", ' ', "EmployeeFred"); - this.verifyRemoveAllWhitespaceOnStringBuffer("\tEmployee\n", ' ', "Employee"); - this.verifyRemoveAllWhitespaceOnStringBuffer("Employee \t Foo", ' ', "EmployeeFoo"); - this.verifyRemoveAllWhitespaceOnStringBuffer(" Emp\tloyee \n Foo", ' ', "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnStringBuffer("Employee Fred\t", "EmployeeFred"); + this.verifyRemoveAllWhitespaceOnStringBuffer("\tEmployee\n", "Employee"); + this.verifyRemoveAllWhitespaceOnStringBuffer("Employee \t Foo", "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnStringBuffer(" Emp\tloyee \n Foo", "EmployeeFoo"); } - private void verifyRemoveAllWhitespaceOnStringBuffer(String string, char charToRemove, String expectedString) { + private void verifyRemoveAllWhitespaceOnStringBuffer(String string, String expectedString) { StringBuffer sb = new StringBuffer(); StringTools.removeAllWhitespaceOn(string, sb); assertEquals(expectedString, sb.toString()); } public void testRemoveAllWhitespaceOnStringBuilder() { - this.verifyRemoveAllWhitespaceOnStringBuilder("Employee Fred\t", ' ', "EmployeeFred"); - this.verifyRemoveAllWhitespaceOnStringBuilder("\tEmployee\n", ' ', "Employee"); - this.verifyRemoveAllWhitespaceOnStringBuilder("Employee \t Foo", ' ', "EmployeeFoo"); - this.verifyRemoveAllWhitespaceOnStringBuilder(" Emp\tloyee \n Foo", ' ', "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnStringBuilder("Employee Fred\t", "EmployeeFred"); + this.verifyRemoveAllWhitespaceOnStringBuilder("\tEmployee\n", "Employee"); + this.verifyRemoveAllWhitespaceOnStringBuilder("Employee \t Foo", "EmployeeFoo"); + this.verifyRemoveAllWhitespaceOnStringBuilder(" Emp\tloyee \n Foo", "EmployeeFoo"); } - private void verifyRemoveAllWhitespaceOnStringBuilder(String string, char charToRemove, String expectedString) { + private void verifyRemoveAllWhitespaceOnStringBuilder(String string, String expectedString) { StringBuilder sb = new StringBuilder(); StringTools.removeAllWhitespaceOn(string, sb); assertEquals(expectedString, sb.toString()); @@ -605,7 +611,7 @@ public class StringToolsTests extends TestCase { } private void verifyCapitalizeCharArray(String expected, char[] string) { - assertEquals(expected, new String(StringTools.capitalize(string))); + assertEquals(expected, StringTools.capitalize(string)); } public void testCapitalizeString() { @@ -729,7 +735,7 @@ public class StringToolsTests extends TestCase { } private void verifyUncapitalizeCharArray(String expected, char[] string) { - assertEquals(expected, new String(StringTools.uncapitalize(string))); + assertEquals(expected, StringTools.uncapitalize(string)); } public void testUncapitalizeString() { @@ -918,7 +924,43 @@ public class StringToolsTests extends TestCase { assertFalse(StringTools.charactersAreEqualIgnoreCase('A', 'b')); } - // ********** conversions ********** + public void testStringIsUppercase() { + this.verifyStringIsUppercase("FOO"); + this.verifyStringIsUppercase("FOO2"); + this.verifyStringIsUppercase("F O O"); + this.denyStringIsUppercase("Foo"); + this.denyStringIsUppercase(""); + } + + private void verifyStringIsUppercase(String s) { + assertTrue(StringTools.stringIsUppercase(s)); + assertTrue(StringTools.stringIsUppercase(s.toCharArray())); + } + + private void denyStringIsUppercase(String s) { + assertFalse(StringTools.stringIsUppercase(s)); + assertFalse(StringTools.stringIsUppercase(s.toCharArray())); + } + + public void testStringIsLowercase() { + this.verifyStringIsLowercase("foo"); + this.verifyStringIsLowercase("foo2"); + this.verifyStringIsLowercase("f o o"); + this.denyStringIsLowercase("Foo"); + this.denyStringIsLowercase(""); + } + + private void verifyStringIsLowercase(String s) { + assertTrue(StringTools.stringIsLowercase(s)); + assertTrue(StringTools.stringIsLowercase(s.toCharArray())); + } + + private void denyStringIsLowercase(String s) { + assertFalse(StringTools.stringIsLowercase(s)); + assertFalse(StringTools.stringIsLowercase(s.toCharArray())); + } + + // ********** convert camel-case to all-caps ********** public void testConvertCamelCaseToAllCaps() { assertEquals("TEST", StringTools.convertCamelCaseToAllCaps("test")); @@ -1047,6 +1089,8 @@ public class StringToolsTests extends TestCase { assertEquals(expected, sb.toString()); } + // ********** convert underscores to all-caps ********** + public void testConvertUnderscoresToCamelCase() { assertEquals("test", StringTools.convertUnderscoresToCamelCase("TEST", false)); assertEquals("test", StringTools.convertUnderscoresToCamelCase("TEST_", false)); @@ -1173,4 +1217,393 @@ public class StringToolsTests extends TestCase { assertEquals(expected, sb.toString()); } + // ********** delimiting ********** + + public void testStringIsQuoted() { + this.denyStringIsQuoted("foo"); + this.verifyStringIsQuoted("\"foo\""); + + this.denyStringIsQuoted(""); + this.verifyStringIsQuoted("\"\""); + + this.denyStringIsQuoted("\""); + this.denyStringIsQuoted(" "); + this.denyStringIsQuoted("''"); + this.denyStringIsQuoted("'foo'"); + } + + private void verifyStringIsQuoted(String s) { + assertTrue(StringTools.stringIsQuoted(s)); + assertTrue(StringTools.stringIsQuoted(s.toCharArray())); + } + + private void denyStringIsQuoted(String s) { + assertFalse(StringTools.stringIsQuoted(s)); + assertFalse(StringTools.stringIsQuoted(s.toCharArray())); + } + + public void testStringIsParenthetical() { + this.denyStringIsParenthetical("foo"); + this.verifyStringIsParenthetical("(foo)"); + + this.denyStringIsParenthetical(""); + this.verifyStringIsParenthetical("()"); + + this.denyStringIsParenthetical("("); + this.denyStringIsParenthetical(" "); + this.denyStringIsParenthetical("''"); + this.denyStringIsParenthetical("'foo'"); + } + + private void verifyStringIsParenthetical(String s) { + assertTrue(StringTools.stringIsParenthetical(s)); + assertTrue(StringTools.stringIsParenthetical(s.toCharArray())); + } + + private void denyStringIsParenthetical(String s) { + assertFalse(StringTools.stringIsParenthetical(s)); + assertFalse(StringTools.stringIsParenthetical(s.toCharArray())); + } + + public void testStringIsBracketed() { + this.denyStringIsBracketed("foo"); + this.verifyStringIsBracketed("[foo]"); + + this.denyStringIsBracketed(""); + this.verifyStringIsBracketed("[]"); + + this.denyStringIsBracketed("["); + this.denyStringIsBracketed(" "); + this.denyStringIsBracketed("''"); + this.denyStringIsBracketed("'foo'"); + } + + private void verifyStringIsBracketed(String s) { + assertTrue(StringTools.stringIsBracketed(s)); + assertTrue(StringTools.stringIsBracketed(s.toCharArray())); + } + + private void denyStringIsBracketed(String s) { + assertFalse(StringTools.stringIsBracketed(s)); + assertFalse(StringTools.stringIsBracketed(s.toCharArray())); + } + + public void testStringIsBraced() { + this.denyStringIsBraced("foo"); + this.verifyStringIsBraced("{foo}"); + + this.denyStringIsBraced(""); + this.verifyStringIsBraced("{}"); + + this.denyStringIsBraced("{"); + this.denyStringIsBraced(" "); + this.denyStringIsBraced("''"); + this.denyStringIsBraced("'foo'"); + } + + private void verifyStringIsBraced(String s) { + assertTrue(StringTools.stringIsBraced(s)); + assertTrue(StringTools.stringIsBraced(s.toCharArray())); + } + + private void denyStringIsBraced(String s) { + assertFalse(StringTools.stringIsBraced(s)); + assertFalse(StringTools.stringIsBraced(s.toCharArray())); + } + + public void testStringIsChevroned() { + this.denyStringIsChevroned("foo"); + this.verifyStringIsChevroned("<foo>"); + + this.denyStringIsChevroned(""); + this.verifyStringIsChevroned("<>"); + + this.denyStringIsChevroned("{"); + this.denyStringIsChevroned(" "); + this.denyStringIsChevroned("''"); + this.denyStringIsChevroned("'foo'"); + } + + private void verifyStringIsChevroned(String s) { + assertTrue(StringTools.stringIsChevroned(s)); + assertTrue(StringTools.stringIsChevroned(s.toCharArray())); + } + + private void denyStringIsChevroned(String s) { + assertFalse(StringTools.stringIsChevroned(s)); + assertFalse(StringTools.stringIsChevroned(s.toCharArray())); + } + + public void testStringIsDelimited() { + this.denyStringIsDelimited("foo", '?'); + this.verifyStringIsDelimited("?foo?", '?'); + + this.denyStringIsDelimited("", '?'); + this.verifyStringIsDelimited("\"\"", '"'); + this.verifyStringIsDelimited("?xx?", '?'); + this.denyStringIsDelimited("?xx]", '?'); + + this.denyStringIsDelimited("\"", '"'); + this.denyStringIsDelimited(" ", ' '); + this.denyStringIsDelimited("''", '"'); + this.denyStringIsDelimited("'foo'", '?'); + } + + private void verifyStringIsDelimited(String s, char c) { + assertTrue(StringTools.stringIsDelimited(s, c)); + assertTrue(StringTools.stringIsDelimited(s.toCharArray(), c)); + } + + private void denyStringIsDelimited(String s, char c) { + assertFalse(StringTools.stringIsDelimited(s, c)); + assertFalse(StringTools.stringIsDelimited(s.toCharArray(), c)); + } + + public void testStringIsDelimited2() { + this.denyStringIsDelimited2("foo", '[', ']'); + this.verifyStringIsDelimited2("{foo}", '{', '}'); + + this.denyStringIsDelimited2("", '[', ']'); + this.verifyStringIsDelimited2("[]", '[', ']'); + this.verifyStringIsDelimited2("[xx]", '[', ']'); + this.denyStringIsDelimited2("?xx]", '[', ']'); + + this.denyStringIsDelimited2("\"", '[', ']'); + this.denyStringIsDelimited2(" ", '[', ']'); + this.denyStringIsDelimited2("''", '[', ']'); + this.denyStringIsDelimited2("'foo'", '[', ']'); + } + + private void verifyStringIsDelimited2(String s, char start, char end) { + assertTrue(StringTools.stringIsDelimited(s, start, end)); + assertTrue(StringTools.stringIsDelimited(s.toCharArray(), start, end)); + } + + private void denyStringIsDelimited2(String s, char start, char end) { + assertFalse(StringTools.stringIsDelimited(s, start, end)); + assertFalse(StringTools.stringIsDelimited(s.toCharArray(), start, end)); + } + + // ********** unwrapping ********** + + public void testUnwrap() { + this.verifyUnwrap("\"foo\"", "foo"); + this.verifyUnwrap("\"\"", ""); + this.verifyUnwrap("'foo'", "foo"); + } + + private void verifyUnwrap(String s, String expected) { + assertEquals(expected, StringTools.unwrap(s)); + assertEquals(expected, StringTools.unwrap(s.toCharArray())); + } + + public void testUnwrapInt() { + this.verifyUnwrapInt("\"foo\"", 2, "o"); + this.verifyUnwrapInt("\"\"foo\"\"", 2, "foo"); + this.verifyUnwrapInt("'foo'", 2, "o"); + } + + private void verifyUnwrapInt(String s, int count, String expected) { + assertEquals(expected, StringTools.unwrap(s, count)); + assertEquals(expected, StringTools.unwrap(s.toCharArray(), count)); + } + + public void testUnwrapIntException() { + this.denyUnwrapInt("\"\"", 2); + this.denyUnwrapInt("'o'", 2); + } + + private void denyUnwrapInt(String s, int count) { + boolean exCaught = false; + try { + String bogus = StringTools.unwrap(s, count); + fail("invalid string: " + bogus); + } catch (IllegalArgumentException ex) { + exCaught = true; + } + assertTrue(exCaught); + + exCaught = false; + try { + char[] bogus = StringTools.unwrap(s.toCharArray(), count); + fail("invalid string: " + new String(bogus)); + } catch (IllegalArgumentException ex) { + exCaught = true; + } + assertTrue(exCaught); + } + + public void testUnwrapOnWriter() { + this.verifyUnwrapOnWriter("\"foo\"", "foo"); + this.verifyUnwrapOnWriter("\"\"", ""); + this.verifyUnwrapOnWriter("'foo'", "foo"); + } + + private void verifyUnwrapOnWriter(String s, String expected) { + Writer writer = new StringWriter(); + StringTools.unwrapOn(s, writer); + assertEquals(expected, writer.toString()); + + writer = new StringWriter(); + StringTools.unwrapOn(s.toCharArray(), writer); + assertEquals(expected, writer.toString()); + } + + public void testUnwrapOnStringBuffer() { + this.verifyUnwrapOnStringBuffer("\"foo\"", "foo"); + this.verifyUnwrapOnStringBuffer("\"\"", ""); + this.verifyUnwrapOnStringBuffer("'foo'", "foo"); + } + + private void verifyUnwrapOnStringBuffer(String s, String expected) { + StringBuffer sb = new StringBuffer(); + StringTools.unwrapOn(s, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuffer(); + StringTools.unwrapOn(s.toCharArray(), sb); + assertEquals(expected, sb.toString()); + } + + public void testUnwrapOnStringBuilder() { + this.verifyUnwrapOnStringBuilder("\"foo\"", "foo"); + this.verifyUnwrapOnStringBuilder("\"\"", ""); + this.verifyUnwrapOnStringBuilder("'foo'", "foo"); + } + + private void verifyUnwrapOnStringBuilder(String s, String expected) { + StringBuilder sb = new StringBuilder(); + StringTools.unwrapOn(s, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuilder(); + StringTools.unwrapOn(s.toCharArray(), sb); + assertEquals(expected, sb.toString()); + } + + public void testUnwrapOnWriterCount() { + this.verifyUnwrapOnWriterCount("\"foo\"", 2, "o"); + this.verifyUnwrapOnWriterCount("\"\"\"\"", 2, ""); + this.verifyUnwrapOnWriterCount("XXfooXX", 2, "foo"); + } + + private void verifyUnwrapOnWriterCount(String s, int count, String expected) { + Writer writer = new StringWriter(); + StringTools.unwrapOn(s, count, writer); + assertEquals(expected, writer.toString()); + + writer = new StringWriter(); + StringTools.unwrapOn(s.toCharArray(), count, writer); + assertEquals(expected, writer.toString()); + } + + public void testUnwrapOnStringBufferCount() { + this.verifyUnwrapOnStringBufferCount("\"foo\"", 2, "o"); + this.verifyUnwrapOnStringBufferCount("\"\"\"\"", 2, ""); + this.verifyUnwrapOnStringBufferCount("XXfooXX", 2, "foo"); + } + + private void verifyUnwrapOnStringBufferCount(String s, int count, String expected) { + StringBuffer sb = new StringBuffer(); + StringTools.unwrapOn(s, count, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuffer(); + StringTools.unwrapOn(s.toCharArray(), count, sb); + assertEquals(expected, sb.toString()); + } + + public void testUnwrapOnStringBuilderCount() { + this.verifyUnwrapOnStringBuilderCount("\"foo\"", 2, "o"); + this.verifyUnwrapOnStringBuilderCount("\"\"\"\"", 2, ""); + this.verifyUnwrapOnStringBuilderCount("XXfooXX", 2, "foo"); + } + + private void verifyUnwrapOnStringBuilderCount(String s, int count, String expected) { + StringBuilder sb = new StringBuilder(); + StringTools.unwrapOn(s, count, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuilder(); + StringTools.unwrapOn(s.toCharArray(), count, sb); + assertEquals(expected, sb.toString()); + } + + // ********** converting to Java string literal ********** + + public void testConvertToJavaStringLiteral() { + this.verifyConvertToJavaStringLiteral("", "\"\""); + this.verifyConvertToJavaStringLiteral("\"\"", "\"\\\"\\\"\""); + this.verifyConvertToJavaStringLiteral("'foo'", "\"'foo'\""); + this.verifyConvertToJavaStringLiteral("foo\bbar", "\"foo\\bbar\""); + this.verifyConvertToJavaStringLiteral("foo\n\tbar", "\"foo\\n\\tbar\""); + this.verifyConvertToJavaStringLiteral("foo\"bar", "\"foo\\\"bar\""); + this.verifyConvertToJavaStringLiteral("foo\\bar", "\"foo\\\\bar\""); + } + + private void verifyConvertToJavaStringLiteral(String s, String expected) { + assertEquals(expected, StringTools.convertToJavaStringLiteral(s)); + assertEquals(expected, StringTools.convertToJavaStringLiteral(s.toCharArray())); + } + + public void testConvertToJavaStringLiteralOnStringBuffer() { + this.verifyConvertToJavaStringLiteralOnStringBuffer("", "\"\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("\"\"", "\"\\\"\\\"\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("'foo'", "\"'foo'\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("foo\bbar", "\"foo\\bbar\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("foo\n\tbar", "\"foo\\n\\tbar\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("foo\"bar", "\"foo\\\"bar\""); + this.verifyConvertToJavaStringLiteralOnStringBuffer("foo\\bar", "\"foo\\\\bar\""); + } + + private void verifyConvertToJavaStringLiteralOnStringBuffer(String s, String expected) { + StringBuffer sb = new StringBuffer(); + StringTools.convertToJavaStringLiteralOn(s, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuffer(); + StringTools.convertToJavaStringLiteralOn(s.toCharArray(), sb); + assertEquals(expected, sb.toString()); + } + + public void testConvertToJavaStringLiteralOnStringBuilder() { + this.verifyConvertToJavaStringLiteralOnStringBuilder("", "\"\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("\"\"", "\"\\\"\\\"\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("'foo'", "\"'foo'\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("foo\bbar", "\"foo\\bbar\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("foo\n\tbar", "\"foo\\n\\tbar\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("foo\"bar", "\"foo\\\"bar\""); + this.verifyConvertToJavaStringLiteralOnStringBuilder("foo\\bar", "\"foo\\\\bar\""); + } + + private void verifyConvertToJavaStringLiteralOnStringBuilder(String s, String expected) { + StringBuilder sb = new StringBuilder(); + StringTools.convertToJavaStringLiteralOn(s, sb); + assertEquals(expected, sb.toString()); + + sb = new StringBuilder(); + StringTools.convertToJavaStringLiteralOn(s.toCharArray(), sb); + assertEquals(expected, sb.toString()); + } + + public void testConvertToJavaStringLiteralOnWriter() { + this.verifyConvertToJavaStringLiteralOnWriter("", "\"\""); + this.verifyConvertToJavaStringLiteralOnWriter("\"\"", "\"\\\"\\\"\""); + this.verifyConvertToJavaStringLiteralOnWriter("'foo'", "\"'foo'\""); + this.verifyConvertToJavaStringLiteralOnWriter("foo\bbar", "\"foo\\bbar\""); + this.verifyConvertToJavaStringLiteralOnWriter("foo\n\tbar", "\"foo\\n\\tbar\""); + this.verifyConvertToJavaStringLiteralOnWriter("foo\"bar", "\"foo\\\"bar\""); + this.verifyConvertToJavaStringLiteralOnWriter("foo\\bar", "\"foo\\\\bar\""); + } + + private void verifyConvertToJavaStringLiteralOnWriter(String s, String expected) { + Writer writer = new StringWriter(); + StringTools.convertToJavaStringLiteralOn(s, writer); + assertEquals(expected, writer.toString()); + + writer = new StringWriter(); + StringTools.convertToJavaStringLiteralOn(s.toCharArray(), writer); + assertEquals(expected, writer.toString()); + } + } |