diff options
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1')
131 files changed, 20334 insertions, 0 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaDataSource.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaDataSource.java new file mode 100644 index 0000000000..e71d6b5f79 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaDataSource.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1; + +import org.eclipse.jpt.core.JpaDataSource; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.internal.AbstractJpaNode; +import org.eclipse.jpt.core.jpa2.JpaFactory2_0; +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.Database; +import org.eclipse.jpt.db.DatabaseIdentifierAdapter; +import org.eclipse.jpt.db.DatabaseObject; + +/** + * GenericJpaDataSource + */ +public class GenericJpaDataSource + extends AbstractJpaNode + implements JpaDataSource +{ + /** + * cache the connection profile name so we can detect when + * it changes and notify listeners + */ + protected String connectionProfileName; + + protected transient ConnectionProfile connectionProfile; + + /** + * listen for the connection to be added or removed or its name changed + */ + protected final ConnectionProfileListener connectionProfileListener; + + /** + * listen for the connection to be opened or closed + */ + protected final ConnectionListener connectionListener; + + private static final long serialVersionUID = 1L; + + + // ********** constructor/initialization ********** + + public GenericJpaDataSource(JpaProject jpaProject, String connectionProfileName) { + super(jpaProject); + //moving the building of the connection profile before the connectionProfileListener + //is added. Need to make sure the loading of db profiles is completed before + //listening, otherwise we get notifications before our model is finished being built. + //this means our updater is called before it is set which results in an IllegalStateException. + //Hopefully this change is temporary and DTP will fix bug 246270 where I suggest they + //not fire events when building profiles. + this.connectionProfileName = connectionProfileName; + this.connectionProfile = this.buildConnectionProfile(connectionProfileName); + + this.connectionProfileListener = this.buildConnectionProfileListener(); + this.getConnectionProfileFactory().addConnectionProfileListener(this.connectionProfileListener); + + this.connectionListener = this.buildConnectionListener(); + if (this.connectionProfile != null) { + this.connectionProfile.addConnectionListener(this.connectionListener); + } + } + + protected ConnectionProfileFactory getConnectionProfileFactory() { + return this.getJpaPlatform().getConnectionProfileFactory(); + } + + protected ConnectionProfileListener buildConnectionProfileListener() { + return new LocalConnectionProfileListener(); + } + + protected ConnectionListener buildConnectionListener() { + return new LocalConnectionListener(); + } + + + // ********** JpaDataSource implementation ********** + + public String getConnectionProfileName() { + return this.connectionProfileName; + } + + public void setConnectionProfileName(String connectionProfileName) { + String old = this.connectionProfileName; + this.connectionProfileName = connectionProfileName; + if (this.attributeValueHasChanged(old, connectionProfileName)) { + this.firePropertyChanged(CONNECTION_PROFILE_NAME_PROPERTY, old, connectionProfileName); + // synch the connection profile when the name changes + this.setConnectionProfile(this.buildConnectionProfile(connectionProfileName)); + JptCorePlugin.setConnectionProfileName(this.getJpaProject().getProject(), connectionProfileName); + } + } + + public ConnectionProfile getConnectionProfile() { + return this.connectionProfile; + } + + @Override + public boolean connectionProfileIsActive() { + ConnectionProfile cp = this.connectionProfile; + return (cp != null) && cp.isActive(); + } + + @Override + public Database getDatabase() { + ConnectionProfile cp = this.connectionProfile; + return (cp == null) ? null : cp.getDatabase(); + } + + public <T extends DatabaseObject> T selectDatabaseObjectForIdentifier(Iterable<T> databaseObjects, String identifier) { + Database db = this.getDatabase(); + return (db == null) ? null : db.selectDatabaseObjectForIdentifier(databaseObjects, identifier); + } + + public void dispose() { + if (this.connectionProfile != null) { + this.connectionProfile.removeConnectionListener(this.connectionListener); + } + this.getConnectionProfileFactory().removeConnectionProfileListener(this.connectionProfileListener); + } + + + // ********** internal methods ********** + + protected ConnectionProfile buildConnectionProfile(String name) { + return this.getConnectionProfileFactory().buildConnectionProfile(name, this.buildDatabaseIdentifierAdapter()); + } + + protected DatabaseIdentifierAdapter buildDatabaseIdentifierAdapter() { + return this.isJpa2_0Compatible() ? + ((JpaFactory2_0) this.getJpaFactory()).buildDatabaseIdentifierAdapter(this) : + DatabaseIdentifierAdapter.Default.instance(); + } + + protected void setConnectionProfile(ConnectionProfile connectionProfile) { + ConnectionProfile old = this.connectionProfile; + if (old != null) { + old.removeConnectionListener(this.connectionListener); + } + this.connectionProfile = connectionProfile; + if (connectionProfile != null) { + connectionProfile.addConnectionListener(this.connectionListener); + } + this.firePropertyChanged(CONNECTION_PROFILE_PROPERTY, old, connectionProfile); + } + + + // ********** overrides ********** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.connectionProfileName); + } + + + // ********** member classes ********** + + /** + * 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(); + } + + 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 + } + } + } + + 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) { + if (newName.equals(GenericJpaDataSource.this.connectionProfileName)) { + GenericJpaDataSource.this.setConnectionProfileName(newName); + } + 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); + } + } + } + + + /** + * Whenever the connection is opened or closed trigger a project update. + */ + protected class LocalConnectionListener extends ConnectionAdapter { + + @Override + public void opened(ConnectionProfile profile) { + GenericJpaDataSource.this.getJpaProject().update(); + } + + @Override + public void closed(ConnectionProfile profile) { + GenericJpaDataSource.this.getJpaProject().update(); + } + + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFactory.java new file mode 100644 index 0000000000..65c0f5237c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFactory.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1; + +import org.eclipse.jpt.core.internal.AbstractJpaFactory; + +/** + * Generic JPA + */ +public class GenericJpaFactory + extends AbstractJpaFactory +{ + public GenericJpaFactory() { + super(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFile.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFile.java new file mode 100644 index 0000000000..7fb2a0f7b6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaFile.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1; + +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jpt.core.JpaFile; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JpaResourceModel; +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.internal.AbstractJpaNode; +import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable; + +/** + * The transition between a JPA project and the resource model associated + * with a file. + * Hold the associated root structure nodes, which are hooks to the + * context model. + */ +public class GenericJpaFile + extends AbstractJpaNode + implements JpaFile +{ + /** + * typically a .java or .xml file. + */ + protected final IFile file; + + /** + * cache the content type - if the content type changes, the JPA project + * will throw out the JPA file and build a new one + */ + protected final IContentType contentType; + + /** + * the resource model corresponding to the file + */ + protected final JpaResourceModel resourceModel; + + /** + * the root structure (context model) nodes corresponding to the resource + * model + */ + protected final Hashtable<Object, JpaStructureNode> rootStructureNodes; + + + // ********** construction ********** + + public GenericJpaFile(JpaProject jpaProject, IFile file, IContentType contentType, JpaResourceModel resourceModel) { + super(jpaProject); + this.file = file; + this.contentType = contentType; + this.resourceModel = resourceModel; + this.rootStructureNodes = new Hashtable<Object, JpaStructureNode>(); + } + + /** + * Changes to ROOT_STRUCTURE_NODES_COLLECTION do not need to trigger a + * project update. Only the UI cares about the root structure nodes. + * If a project update is allowed to happen, an infinite loop will result + * if any java class is specified in more than one location in the + * persistence unit. + */ + @Override + protected void addNonUpdateAspectNamesTo(Set<String> nonUpdateAspectNames) { + super.addNonUpdateAspectNamesTo(nonUpdateAspectNames); + nonUpdateAspectNames.add(ROOT_STRUCTURE_NODES_COLLECTION); + } + + + // ********** file ********** + + public IFile getFile() { + return this.file; + } + + public IContentType getContentType() { + return this.contentType; + } + + public JpaResourceModel getResourceModel() { + return this.resourceModel; + } + + public JpaResourceModel getResourceModel(IContentType ct) { + return this.contentType.isKindOf(ct) ? this.resourceModel : null; + } + + + // ********** root structure nodes ********** + + public Iterator<JpaStructureNode> rootStructureNodes() { + return this.getRootStructureNodes().iterator(); + } + + protected Iterable<JpaStructureNode> getRootStructureNodes() { + return new LiveCloneIterable<JpaStructureNode>(this.rootStructureNodes.values()); + } + + public int rootStructureNodesSize() { + return this.rootStructureNodes.size(); + } + + public void addRootStructureNode(Object key, JpaStructureNode rootStructureNode) { + JpaStructureNode old = this.rootStructureNodes.put(key, rootStructureNode); + if (rootStructureNode != old) { + if (old != null) { + this.fireItemRemoved(ROOT_STRUCTURE_NODES_COLLECTION, old); + } + this.fireItemAdded(ROOT_STRUCTURE_NODES_COLLECTION, rootStructureNode); + } + } + + public void removeRootStructureNode(Object key) { + this.fireItemRemoved(ROOT_STRUCTURE_NODES_COLLECTION, this.rootStructureNodes.remove(key)); + } + + public JpaStructureNode getStructureNode(int textOffset) { + for (JpaStructureNode rootNode : this.getRootStructureNodes()) { + JpaStructureNode node = rootNode.getStructureNode(textOffset); + if (node != null) { + return node; + } + } + return null; + } + + + // ********** misc ********** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.file); + sb.append('['); + sb.append(this.contentType.getName()); + sb.append(']'); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java new file mode 100644 index 0000000000..7d0c986d6f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1; + +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.internal.AbstractJpaProject; + +/** + * Not much different from the abstract JPA project. + */ +public class GenericJpaProject + extends AbstractJpaProject +{ + + // ********** constructor/initialization ********** + + public GenericJpaProject(JpaProject.Config config) { + super(config); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java new file mode 100644 index 0000000000..48e1a0fa02 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2011 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.jpa1.context; + +import java.util.List; + +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.IdClassReference; +import org.eclipse.jpt.core.internal.context.PrimaryKeyTextRangeResolver; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractEntityPrimaryKeyValidator extends + AbstractPrimaryKeyValidator { + + public AbstractEntityPrimaryKeyValidator(Entity entity, + PrimaryKeyTextRangeResolver textRangeResolver) { + super(entity, textRangeResolver); + } + + protected Entity entity() { + return (Entity) this.typeMapping(); + } + + @Override + protected IdClassReference idClassReference() { + return entity().getIdClassReference(); + } + + public void validate(List<IMessage> messages, IReporter reporter) { + // if an entity is non-root, it is not allowed to define primary keys + if (! entity().isRoot()) { + validatePrimaryKeyForNonRoot(messages, reporter); + } + else { + validatePrimaryKeyForRoot(messages, reporter); + } + } + + protected void validatePrimaryKeyForNonRoot(List<IMessage> messages, IReporter reporter) { + validateNonRootEntityDoesNotSpecifyIdClass(messages, reporter); + validateNonRootEntityDoesNotSpecifyPrimaryKeyAttributes(messages, reporter); + } + + protected void validatePrimaryKeyForRoot(List<IMessage> messages, IReporter reporter) { + validatePrimaryKeyIsNotRedefined(messages, reporter); + validateIdClassIsUsedIfNecessary(messages, reporter); + + // if the primary key is not defined on an ancestor, it must be defined here + if (! definesPrimaryKey(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NO_PK, + new String[0], + entity(), + textRangeResolver().getTypeMappingTextRange())); + } + + // if primary key is composite, it may either use an id class or embedded id, not both + validateOneOfIdClassOrEmbeddedIdIsUsed(messages, reporter); + // ... and only one embedded id + validateOneEmbeddedId(messages, reporter); + + validateMapsIdMappings(messages, reporter); + + if (specifiesIdClass()) { + validateIdClass(idClassReference().getIdClass(), messages, reporter); + } + } + + protected void validateNonRootEntityDoesNotSpecifyIdClass(List<IMessage> messages, IReporter reporter) { + if (idClassReference().isSpecified()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NON_ROOT_ID_CLASS_SPECIFIED, + new String[0], + entity(), + textRangeResolver().getIdClassTextRange())); + } + } + + protected void validateNonRootEntityDoesNotSpecifyPrimaryKeyAttributes(List<IMessage> messages, IReporter reporter) { + for (AttributeMapping each : getPrimaryKeyMappingsDefinedLocally(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NON_ROOT_ID_ATTRIBUTE_SPECIFIED, + new String[0], + each, + textRangeResolver().getAttributeMappingTextRange(each.getName()))); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java new file mode 100644 index 0000000000..364cedfd27 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.core.context.IdClassReference; +import org.eclipse.jpt.core.context.MappedSuperclass; +import org.eclipse.jpt.core.internal.context.PrimaryKeyTextRangeResolver; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractMappedSuperclassPrimaryKeyValidator + extends AbstractPrimaryKeyValidator +{ + public AbstractMappedSuperclassPrimaryKeyValidator( + MappedSuperclass mappedSuperclass, PrimaryKeyTextRangeResolver textRangeResolver) { + + super(mappedSuperclass, textRangeResolver); + } + + + protected MappedSuperclass mappedSuperclass() { + return (MappedSuperclass) this.typeMapping(); + } + + @Override + protected IdClassReference idClassReference() { + return mappedSuperclass().getIdClassReference(); + } + + public void validate(List<IMessage> messages, IReporter reporter) { + validatePrimaryKeyIsNotRedefined(messages, reporter); + validateIdClassIsUsedIfNecessary(messages, reporter); + + // if primary key is composite, it may either use an id class or embedded id, not both + validateOneOfIdClassOrEmbeddedIdIsUsed(messages, reporter); + // ... and only one embedded id + validateOneEmbeddedId(messages, reporter); + + if (specifiesIdClass()) { + validateIdClass(idClassReference().getIdClass(), messages, reporter); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java new file mode 100644 index 0000000000..b39e362915 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java @@ -0,0 +1,589 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.EmbeddedIdMapping; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.IdClassReference; +import org.eclipse.jpt.core.context.IdMapping; +import org.eclipse.jpt.core.context.PersistentAttribute; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.internal.context.PrimaryKeyTextRangeResolver; +import org.eclipse.jpt.core.internal.context.PrimaryKeyValidator; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.jpt.utility.internal.ClassName; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.HashBag; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractPrimaryKeyValidator + implements PrimaryKeyValidator +{ + private TypeMapping typeMapping; + + private PrimaryKeyTextRangeResolver textRangeResolver; + + + protected AbstractPrimaryKeyValidator( + TypeMapping typeMapping, PrimaryKeyTextRangeResolver textRangeResolver) { + + this.typeMapping = typeMapping; + this.textRangeResolver = textRangeResolver; + } + + + protected TypeMapping typeMapping() { + return this.typeMapping; + } + + protected abstract IdClassReference idClassReference(); + + protected PrimaryKeyTextRangeResolver textRangeResolver() { + return this.textRangeResolver; + } + + // for JPA portability, a hierarchy must define its primary key on one class + // (entity *or* mapped superclass) + protected void validatePrimaryKeyIsNotRedefined(List<IMessage> messages, IReporter reporter) { + if (definesPrimaryKeyOnAncestor(typeMapping())) { + if (idClassReference().isSpecified()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_CLASS, + new String[0], + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + for (AttributeMapping each : getPrimaryKeyMappingsDefinedLocally(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_ATTRIBUTE, + new String[0], + each, + textRangeResolver().getAttributeMappingTextRange(each.getName()))); + } + return; + } + } + + // if a primary key defining class has multiple primary keys, it must use an id class + protected void validateIdClassIsUsedIfNecessary(List<IMessage> messages, IReporter reporter) { + if (! specifiesIdClass() && idClassIsRequired()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_REQUIRED, + new String[0], + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + // only one composite primary key strategy may be used + protected void validateOneOfIdClassOrEmbeddedIdIsUsed(List<IMessage> messages, IReporter reporter) { + if (idClassReference().isSpecified() + && CollectionTools.size(typeMapping().getAllAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)) > 0) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_AND_EMBEDDED_ID_BOTH_USED, + new String[0], + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + // only one embedded id may be used + protected void validateOneEmbeddedId(List<IMessage> messages, IReporter reporter) { + if (CollectionTools.size(getEmbeddedIdMappings(typeMapping())) > 1) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_MULTIPLE_EMBEDDED_ID, + new String[0], + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + protected void validateMapsIdMappings(List<IMessage> messages, IReporter reporter) { + for (SingleRelationshipMapping2_0 mapsIdRelationshipMapping : getMapsIdMappingsDefinedLocally(typeMapping())) { + // can't use maps id mappings with an id class + if (definesIdClass(typeMapping())) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_WITH_MAPS_ID, + new String[] {mapsIdRelationshipMapping.getName()}, + mapsIdRelationshipMapping, + textRangeResolver().getAttributeMappingTextRange(mapsIdRelationshipMapping.getName()))); + } + + AttributeMapping resolvedAttributeMapping = + mapsIdRelationshipMapping.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getResolvedAttributeMappingValue(); + if (resolvedAttributeMapping != null + && ! ClassName.areAutoboxEquivalents( + resolvedAttributeMapping.getPersistentAttribute().getTypeName(), + getTargetEntityPrimaryKeyTypeName(mapsIdRelationshipMapping))) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_MAPS_ID_ATTRIBUTE_TYPE_DOES_NOT_AGREE, + new String[] {mapsIdRelationshipMapping.getName()}, + mapsIdRelationshipMapping, + textRangeResolver().getAttributeMappingTextRange(mapsIdRelationshipMapping.getName()))); + } + } + } + + protected void validateIdClass(JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) { + // there should already be a validation error if the id class does not resolve to a class + if (idClass == null) { + return; + } + + if (hasDerivedIdMappingMatchingIdClass(idClass)) { + validateIdClass_derivedIdMappingMatchingIdClass(idClass, messages, reporter); + return; + } + for (JavaPersistentAttribute idClassAttribute : + new SubIterableWrapper<PersistentAttribute, JavaPersistentAttribute>( + CollectionTools.iterable(idClass.allAttributes()))) { + boolean foundMatch = false; + for (AttributeMapping attributeMapping : getAttributeMappings(typeMapping())) { + if (idClassAttribute.getName().equals(attributeMapping.getName())) { + foundMatch = true; + + // the matching attribute should be a primary key + if (! definesPrimaryKey(attributeMapping)) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NOT_PRIMARY_KEY, + new String[] {idClassAttribute.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + // the matching attribute's type should agree + String idClassAttributeTypeName = idClassAttribute.getTypeName(); + String attributeMappingTypeName = getTypeNameForIdClass(attributeMapping); + if (attributeMappingTypeName != null // if it's null, there should be + // another failing validation elsewhere + && ! ClassName.areAutoboxEquivalents(idClassAttributeTypeName, attributeMappingTypeName)) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_TYPE_DOES_NOT_AGREE, + new String[] {idClassAttribute.getName(), idClassAttributeTypeName}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + } + } + + if (! foundMatch) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NO_MATCH, + new String[] {idClassAttribute.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + } + } + + protected void validateIdClass_derivedIdMappingMatchingIdClass( + JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) { + + Collection<AttributeMapping> errorMappings = new HashBag<AttributeMapping>(); + for (AttributeMapping each + : new CompositeIterable<AttributeMapping>(getIdMappings(typeMapping()), getEmbeddedIdMappings(typeMapping()))) { + errorMappings.add(each); + } + Collection<AttributeMapping> errorDerivedIdMappings = new HashBag<AttributeMapping>(); + for (SingleRelationshipMapping2_0 each : getDerivedIdMappings(typeMapping())) { + if (idClass.getName().equals(getTargetEntityPrimaryKeyTypeName(each))) { + errorDerivedIdMappings.add(each); + } + else { + errorMappings.add(each); + } + } + for (AttributeMapping each : errorMappings) { + addNoIdClassAttributeMatchError(each, messages); + } + if (CollectionTools.size(errorDerivedIdMappings) > 1) { + for (AttributeMapping each : errorDerivedIdMappings) { + addDuplicateIdClassAttributeMatchError(each, messages); + } + } + } + + protected void addNoIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_NO_MATCH, + new String[] {attributeMapping.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + protected void addDuplicateIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_DUPLICATE_MATCH, + new String[] {attributeMapping.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + + // **************** convenience methods ******************************************************** + + // **************** primary key overall ******************************************************** + + /** + * Return whether an ancestor class has defined any aspect of the primary key + */ + protected boolean definesPrimaryKeyOnAncestor(TypeMapping typeMapping) { + for (TypeMapping each : CollectionTools.iterable(typeMapping.inheritanceHierarchy())) { + if (each != typeMapping && definesPrimaryKey(each)) { + return true; + } + } + return false; + } + + /** + * Return whether the type mapping has defined any aspect of the primary key + */ + protected boolean definesPrimaryKey(TypeMapping typeMapping) { + return getIdClass(typeMapping) != null + || ! CollectionTools.isEmpty(getPrimaryKeyMappings(typeMapping)); + } + + /** + * Return true if the type mapping has defined any aspect of a complex primary key + */ + protected boolean definesComplexPrimaryKey(TypeMapping typeMapping) { + return definesIdClass(typeMapping) + || getEmbeddedIdMapping(typeMapping) != null; + } + + /** + * Return the overriding type name of the primary key for the type mapping. + * This may be + * - type of the single simple primary key (id) attribute + * - type of the single complex primary key (embedded id) attribute + * - type of the id class + * - null if none of the above are coherent (i.e. there are multiple possibilities, or the + * primary key is invalid) + */ + protected String getPrimaryKeyTypeName(TypeMapping typeMapping) { + JavaPersistentType idClass = getIdClass(typeMapping); + if (idClass != null) { + return idClass.getName(); + } + EmbeddedIdMapping embeddedId = getEmbeddedIdMapping(typeMapping); + if (embeddedId != null) { + return embeddedId.getPersistentAttribute().getTypeName(); + } + IdMapping id = getIdMapping(typeMapping); + if (id != null) { + return id.getPersistentAttribute().getTypeName(); + } + return null; + } + + /** + * Return whether the attribute mapping has defined any aspect of the primary key + */ + protected boolean definesPrimaryKey(AttributeMapping attributeMapping) { + String mappingKey = attributeMapping.getKey(); + if (StringTools.stringsAreEqual(mappingKey, MappingKeys.ID_ATTRIBUTE_MAPPING_KEY) + || StringTools.stringsAreEqual(mappingKey, MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY)) { + return true; + } + if (StringTools.stringsAreEqual(mappingKey, MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) + || StringTools.stringsAreEqual(mappingKey, MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY)) { + SingleRelationshipMapping2_0 relationshipMapping = (SingleRelationshipMapping2_0) attributeMapping; + return (relationshipMapping.getDerivedIdentity().usesIdDerivedIdentityStrategy() + || relationshipMapping.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy()); + } + return false; + } + + + // **************** id class ********************************************** + + protected boolean specifiesIdClass() { + return idClassReference().isSpecified(); + } + + /** + * Return whether an id class is defined on the class + * NOTE: this is different from whether an id class is *specified*. If a specified id class + * is not resolved, it is not defined. There will be a validation error to that effect. + */ + protected boolean definesIdClass(TypeMapping typeMapping) { + return getIdClass(typeMapping) != null; + } + + /** + * Return whether an ancestor class has defined an id class + */ + protected boolean definesIdClassOnAncestor(TypeMapping typeMapping) { + for (TypeMapping each : CollectionTools.iterable(typeMapping.inheritanceHierarchy())) { + if (each != typeMapping && definesIdClass(each)) { + return true; + } + } + return false; + } + + /** + * Return the id class to be used for the type mapping, whether that be locally + * or on an ancestor + */ + protected JavaPersistentType getIdClass(TypeMapping typeMapping) { + for (Iterator<TypeMapping> stream = typeMapping.inheritanceHierarchy(); stream.hasNext(); ) { + TypeMapping next = stream.next(); + if (next.getIdClass() != null) { + return next.getIdClass(); + } + } + return null; + } + + + // **************** attribute mappings in general ************************* + + protected Iterable<AttributeMapping> getAttributeMappings(TypeMapping typeMapping) { + return CollectionTools.collection(typeMapping.allAttributeMappings()); + } + + /** + * Return all primary key mappings, defined on and above the type mapping + */ + protected Iterable<AttributeMapping> getPrimaryKeyMappings(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + getIdMappings(typeMapping), + getEmbeddedIdMappings(typeMapping), + getDerivedIdMappings(typeMapping), + getMapsIdMappings(typeMapping)); + } + + /** + * Return primary key mappings declared directly on the type mapping + */ + protected Iterable<AttributeMapping> getPrimaryKeyMappingsDefinedLocally(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + getIdMappingsDefinedLocally(typeMapping), + getEmbeddedIdMappingsDefinedLocally(typeMapping), + getDerivedIdMappingsDefinedLocally(typeMapping), + getMapsIdMappingsDefinedLocally(typeMapping)); + } + + protected boolean hasAnyPrimaryKeyMappings(TypeMapping typeMapping) { + return ! CollectionTools.isEmpty(getPrimaryKeyMappings(typeMapping)); + } + + // **************** id mappings ******************************************* + + protected IdMapping getIdMapping(TypeMapping typeMapping) { + Iterable<IdMapping> idMappings = getIdMappings(typeMapping); + if (CollectionTools.size(idMappings) == 1) { + return idMappings.iterator().next(); + } + return null; + } + + protected Iterable<IdMapping> getIdMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, IdMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY)); + } + + protected Iterable<IdMapping> getIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, IdMapping>( + typeMapping.getAttributeMappings(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY)); + } + + + // **************** embedded id mappings ********************************** + + /** + * Return whether an embedded id is defined for this class, whether that be locally + * or on an ancestor + */ + protected boolean definesEmbeddedIdMapping(TypeMapping typeMapping) { + return ! CollectionTools.isEmpty(getEmbeddedIdMappings(typeMapping)); + } + + protected EmbeddedIdMapping getEmbeddedIdMapping(TypeMapping typeMapping) { + Iterable<EmbeddedIdMapping> embeddedIdMappings = getEmbeddedIdMappings(typeMapping); + if (CollectionTools.size(embeddedIdMappings) == 1) { + return embeddedIdMappings.iterator().next(); + } + return null; + } + + protected Iterable<EmbeddedIdMapping> getEmbeddedIdMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, EmbeddedIdMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)); + } + + protected Iterable<EmbeddedIdMapping> getEmbeddedIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, EmbeddedIdMapping>( + typeMapping.getAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)); + } + + + // **************** derived id mappings *********************************** + + protected Iterable<SingleRelationshipMapping2_0> getDerivedIdMappings(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesIdDerivedIdentityStrategy(); + } + }; + } + + protected Iterable<SingleRelationshipMapping2_0> getDerivedIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + typeMapping.getAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** maps id mappings ************************************** + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdMappings(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + typeMapping.getAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** misc ************************************************** + + /** + * Return whether an id class is required for this class + */ + protected boolean idClassIsRequired() { + // An id class is required if + // - there are multiple "simple" primary key mappings + // - or there is at least one "complex" primary key mapping + // A simple primary key mapping can be + // - an id mapping + // - a derived id relationship mapping to an entity with a simple primary key + // A complex primary key mapping can be + // - a derived id relationship mapping to an entity with a complex primary key + int simplePrimaryKeyMappingCount = + CollectionTools.size(getIdMappings(typeMapping())); + if (simplePrimaryKeyMappingCount > 1) { + return true; + } + for (SingleRelationshipMapping2_0 relationshipMapping : getDerivedIdMappings(typeMapping())) { + Entity entity = relationshipMapping.getResolvedTargetEntity(); + if (entity != null) { + if (definesComplexPrimaryKey(entity)) { + return true; + } + else { + simplePrimaryKeyMappingCount++; + } + if (simplePrimaryKeyMappingCount > 1) { + return true; + } + } + } + return false; + } + + protected boolean hasDerivedIdMappingMatchingIdClass(JavaPersistentType idClass) { + for (SingleRelationshipMapping2_0 each : getDerivedIdMappings(typeMapping())) { + String primaryKeyTypeName = getTargetEntityPrimaryKeyTypeName(each); + if (idClass.getName().equals(primaryKeyTypeName)) { + return true; + } + } + return false; + } + + protected String getTargetEntityPrimaryKeyTypeName(SingleRelationshipMapping2_0 relationshipMapping) { + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity != null) { + return getPrimaryKeyTypeName(targetEntity); + } + return null; + } + + protected String getTypeNameForIdClass(AttributeMapping attributeMapping) { + if (StringTools.stringsAreEqual(attributeMapping.getKey(), MappingKeys.ID_ATTRIBUTE_MAPPING_KEY) + || StringTools.stringsAreEqual(attributeMapping.getKey(), MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)) { + return attributeMapping.getPersistentAttribute().getTypeName(); + } + if (StringTools.stringsAreEqual(attributeMapping.getKey(), MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) + || StringTools.stringsAreEqual(attributeMapping.getKey(), MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY)) { + SingleRelationshipMapping2_0 relationshipMapping = (SingleRelationshipMapping2_0) attributeMapping; + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity != null) { + return getPrimaryKeyTypeName(targetEntity); + } + } + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java new file mode 100644 index 0000000000..2ef9b73cb2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context; + +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.internal.context.PrimaryKeyTextRangeResolver; + +public class GenericEntityPrimaryKeyValidator + extends AbstractEntityPrimaryKeyValidator +{ + public GenericEntityPrimaryKeyValidator(Entity entity, PrimaryKeyTextRangeResolver textRangeResolver) { + super(entity, textRangeResolver); + } + + @Override + protected boolean idClassIsRequired() { + //Short circuit check for idClassIsRequired if any part of the primary key is defined + //in a superclass for Generic types. Other validation will exist and needs to be + //addressed first + if(definesPrimaryKeyOnAncestor(typeMapping())){ + return false; + } + return super.idClassIsRequired(); + } + + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java new file mode 100644 index 0000000000..b9b47ad7bf --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context; + +import org.eclipse.jpt.core.context.MappedSuperclass; +import org.eclipse.jpt.core.internal.context.PrimaryKeyTextRangeResolver; + +public class GenericMappedSuperclassPrimaryKeyValidator extends + AbstractMappedSuperclassPrimaryKeyValidator { + + public GenericMappedSuperclassPrimaryKeyValidator(MappedSuperclass mappedSuperclass, PrimaryKeyTextRangeResolver textRangeResolver) { + super(mappedSuperclass, textRangeResolver); + } + + @Override + protected boolean idClassIsRequired() { + //Short circuit check for idClassIsRequired if any part of the primary key is defined + //in a superclass for Generic types. Other validation will exist and needs to be + //addressed first + if(definesPrimaryKeyOnAncestor(typeMapping())){ + return false; + } + return super.idClassIsRequired(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericRootContextNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericRootContextNode.java new file mode 100644 index 0000000000..1625ac7ff4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/GenericRootContextNode.java @@ -0,0 +1,282 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context; + +import java.util.List; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jpt.core.JpaProject; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.MappingFileRoot; +import org.eclipse.jpt.core.context.persistence.Persistence; +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.context.persistence.PersistenceXml; +import org.eclipse.jpt.core.internal.context.AbstractJpaContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.JpaRootContextNode2_0; +import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceXml2_0; +import org.eclipse.jpt.core.resource.java.JavaResourceCompilationUnit; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.xml.JpaXmlResource; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.HashBag; +import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * the context model root + */ +public class GenericRootContextNode + extends AbstractJpaContextNode + implements JpaRootContextNode2_0 +{ + /* This object has no parent, so it must point to the JPA project explicitly. */ + protected final JpaProject jpaProject; + + /* Main context object. */ + protected PersistenceXml persistenceXml; + + + public GenericRootContextNode(JpaProject jpaProject) { + super(null); // the JPA project is not really a "parent"... + if (jpaProject == null) { + throw new NullPointerException(); + } + this.jpaProject = jpaProject; + this.initialize(); + } + + + @Override + protected boolean requiresParent() { + return false; + } + + protected void initialize() { + JpaXmlResource resource = this.resolvePersistenceXmlResource(); + if (resource != null) { + this.persistenceXml = this.buildPersistenceXml(resource); + } + } + + public void update(IProgressMonitor monitor) { + JpaXmlResource xmlResource = this.resolvePersistenceXmlResource(); + if (xmlResource == null) { + if (this.persistenceXml != null) { + this.persistenceXml.dispose(); + this.setPersistenceXml(null); + } + } else { + if (this.persistenceXml == null) { + this.setPersistenceXml(this.buildPersistenceXml(xmlResource)); + } else { + this.persistenceXml.update(); + } + } + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.persistenceXml != null) { + this.persistenceXml.postUpdate(); + } + } + + + // ********** AbstractJpaNode overrides ********** + + @Override + public JpaProject getJpaProject() { + return this.jpaProject; + } + + @Override + public IResource getResource() { + return this.getProject(); + } + + protected IProject getProject() { + return this.jpaProject.getProject(); + } + + + // ********** AbstractJpaContextNode overrides ********** + + @Override + public PersistenceUnit getPersistenceUnit() { + return null; + } + + @Override + public MappingFileRoot getMappingFileRoot() { + return null; + } + + + // ********** persistence.xml ********** + + public PersistenceXml getPersistenceXml() { + return this.persistenceXml; + } + + protected void setPersistenceXml(PersistenceXml persistenceXml) { + PersistenceXml old = this.persistenceXml; + this.persistenceXml = persistenceXml; + this.firePropertyChanged(PERSISTENCE_XML_PROPERTY, old, persistenceXml); + } + + protected JpaXmlResource resolvePersistenceXmlResource() { + JpaXmlResource xmlResource = this.jpaProject.getPersistenceXmlResource(); + if (xmlResource == null) { + return null; + } + if (xmlResource.isReverting()) { + // 308254 - this can happen when persistence.xml is closed without saving; + // the model is completely whacked in another thread - so wipe our model(?) + return null; + } + JpaResourceType resourceType = xmlResource.getResourceType(); + if (resourceType == null) { + return null; + } + if ( ! this.getJpaPlatform().supportsResourceType(resourceType)) { + return null; + } + return xmlResource; + } + + protected PersistenceXml buildPersistenceXml(JpaXmlResource resource) { + return this.getJpaFactory().buildPersistenceXml(this, resource); + } + + + // ********** metamodel ********** + + public void initializeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).disposeMetamodel(); + } + } + + + // ********** validation ********** + + public void validate(List<IMessage> messages, IReporter reporter) { + if (reporter.isCancelled()) { + throw new ValidationCancelledException(); + } + + if (this.persistenceXml == null) { + messages.add(buildPersistenceXmlValidationMessage()); + return; + } + if ( ! this.jpaProject.discoversAnnotatedClasses()) { + this.validateOrphanClasses(messages); + } + this.persistenceXml.validate(messages, reporter); + } + + protected IMessage buildPersistenceXmlValidationMessage() { + int severity = IMessage.HIGH_SEVERITY; + IFile file = getPlatformFile(); + if (file.exists()) { + JpaXmlResource xmlResource = this.jpaProject.getPersistenceXmlResource(); + if (xmlResource != null + && ! getJpaPlatform().supportsResourceType(xmlResource.getResourceType())) { + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PERSISTENCE_XML_UNSUPPORTED_CONTENT, + file); + } + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PERSISTENCE_XML_INVALID_CONTENT, + file); + } + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PROJECT_NO_PERSISTENCE_XML, + this); + } + + protected IFile getPlatformFile() { + return this.jpaProject.convertToPlatformFile(JptCorePlugin.DEFAULT_PERSISTENCE_XML_FILE_PATH); + } + + protected void validateOrphanClasses(List<IMessage> messages) { + Persistence persistence = this.persistenceXml.getPersistence(); + if (persistence == null) { + return; // handled with other validation + } + if (persistence.persistenceUnitsSize() != 1) { + return; // the context model currently only supports 1 persistence unit + } + + PersistenceUnit persistenceUnit = persistence.persistenceUnits().next(); + HashBag<String> annotatedClassNames = CollectionTools.bag(this.jpaProject.annotatedJavaSourceClassNames()); + HashBag<String> orphans = annotatedClassNames.clone(); + for (String annotatedClassName : annotatedClassNames) { + if (persistenceUnit.specifiesPersistentType(annotatedClassName)) { + orphans.remove(annotatedClassName); + } + } + + // TODO remove 'jrcu' + // replace jrcu.getFile() with jrpt.getFile() + // replace jrpt.getMappingAnnotation().getTextRange(jrcu.buildASTRoot()) + // with jrpt.getMappingAnnotation().getTextRange() + // (new method #getTextRange() ?) + for (String orphan : orphans) { + JavaResourcePersistentType jrpt = this.jpaProject.getJavaResourcePersistentType(orphan); + JavaResourceCompilationUnit jrcu = jrpt.getJavaResourceCompilationUnit(); + if (jrpt.isMapped()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_MAPPED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT, + new String[] {jrpt.getName()}, + jrpt.getFile(), + jrpt.getNameTextRange(jrcu.buildASTRoot()) + ) + ); + } + else { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_ANNOTATED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT, + new String[] {jrpt.getName()}, + jrpt.getFile(), + jrpt.getNameTextRange(jrcu.buildASTRoot()) + ) + ); + } + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJarFile.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJarFile.java new file mode 100644 index 0000000000..f25606219d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJarFile.java @@ -0,0 +1,211 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.PersistentType; +import org.eclipse.jpt.core.context.java.JarFile; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.context.persistence.JarFileRef; +import org.eclipse.jpt.core.internal.context.AbstractJpaContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourcePackageFragmentRoot; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.HashBag; +import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; +import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Context JAR file + */ +public class GenericJarFile + extends AbstractJpaContextNode + implements JarFile, PersistentType.Owner +{ + protected JavaResourcePackageFragmentRoot jarResourcePackageFragmentRoot; + protected final Vector<JavaPersistentType> javaPersistentTypes = new Vector<JavaPersistentType>(); + + + // ********** constructor/initialization ********** + + public GenericJarFile(JarFileRef parent, JavaResourcePackageFragmentRoot jarResourcePackageFragmentRoot) { + super(parent); + this.jarResourcePackageFragmentRoot = jarResourcePackageFragmentRoot; + CollectionTools.addAll(this.javaPersistentTypes, this.buildJavaPersistentTypes()); + } + + protected Iterator<JavaPersistentType> buildJavaPersistentTypes() { + return new TransformationIterator<JavaResourcePersistentType, JavaPersistentType>(this.javaResourcePersistentTypes()) { + @Override + protected JavaPersistentType transform(JavaResourcePersistentType jrpt) { + return GenericJarFile.this.buildJavaPersistentType(jrpt); + } + }; + } + + /** + * the resource JAR holds only annotated types, so we can use them all for + * building the context types + */ + protected Iterator<JavaResourcePersistentType> javaResourcePersistentTypes() { + return this.jarResourcePackageFragmentRoot.persistentTypes(); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return null; + } + + @Override + public JpaResourceType getResourceType() { + return JptCorePlugin.JAR_RESOURCE_TYPE; + } + + public TextRange getSelectionTextRange() { + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + return null; + } + + public void dispose() { + // nothing yet + } + + + // ********** JarFile implementation ********** + + public JavaPersistentType getPersistentType(String typeName) { + for (JavaPersistentType pt : this.getJavaPersistentTypes()) { + if (pt.getName().equals(typeName)) { + return pt; + } + } + return null; + } + + public Iterator<JavaPersistentType> javaPersistentTypes() { + return this.getJavaPersistentTypes().iterator(); + } + + protected Iterable<JavaPersistentType> getJavaPersistentTypes() { + return new LiveCloneIterable<JavaPersistentType>(this.javaPersistentTypes); + } + + public int javaPersistentTypesSize() { + return this.javaPersistentTypes.size(); + } + + protected JavaPersistentType addJavaPersistentType(JavaResourcePersistentType jrpt) { + JavaPersistentType javaPersistentType = this.buildJavaPersistentType(jrpt); + this.addItemToCollection(javaPersistentType, this.javaPersistentTypes, JAVA_PERSISTENT_TYPES_COLLECTION); + return javaPersistentType; + } + + protected void removeJavaPersistentType(JavaPersistentType javaPersistentType ) { + this.removeItemFromCollection(javaPersistentType, this.javaPersistentTypes, JAVA_PERSISTENT_TYPES_COLLECTION); + } + + + // ********** PersistentTypeContainer implementation ********** + + public Iterable<? extends PersistentType> getPersistentTypes() { + return this.getJavaPersistentTypes(); + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getDefaultPersistentTypeAccess() { + return this.getPersistenceUnit().getDefaultAccess(); + } + + public AccessType getOverridePersistentTypeAccess() { + // no access type at this level overrides any local access type specification + return null; + } + + + // ********** JpaNode implementation ********** + + @Override + public IResource getResource() { + return this.jarResourcePackageFragmentRoot.getFile(); + } + + + // ********** updating ********** + + public void update(JavaResourcePackageFragmentRoot jrpfr) { + this.jarResourcePackageFragmentRoot = jrpfr; + this.updateJavaPersistentTypes(); + } + + protected void updateJavaPersistentTypes() { + HashBag<JavaPersistentType> contextTypesToRemove = CollectionTools.bag(this.javaPersistentTypes(), this.javaPersistentTypes.size()); + ArrayList<JavaPersistentType> contextTypesToUpdate = new ArrayList<JavaPersistentType>(this.javaPersistentTypes.size()); + + for (Iterator<JavaResourcePersistentType> resourceTypes = this.javaResourcePersistentTypes(); resourceTypes.hasNext(); ) { + JavaResourcePersistentType resourceType = resourceTypes.next(); + boolean match = false; + for (Iterator<JavaPersistentType> contextTypes = contextTypesToRemove.iterator(); contextTypes.hasNext(); ) { + JavaPersistentType contextType = contextTypes.next(); + if (contextType.getResourcePersistentType() == resourceType) { + contextTypes.remove(); + contextTypesToUpdate.add(contextType); + match = true; + break; + } + } + if ( ! match) { + this.addJavaPersistentType(resourceType); + } + } + for (JavaPersistentType contextType : contextTypesToRemove) { + this.removeJavaPersistentType(contextType); + } + // handle adding and removing java persistent types first, update the + // remaining java persistent types last; this reduces the churn during "update" + for (JavaPersistentType contextType : contextTypesToUpdate) { + contextType.update(); + } + } + + + // ********** validation ********** + + public void validate(List<IMessage> messages, IReporter reporter) { + if (reporter.isCancelled()) { + throw new ValidationCancelledException(); + } + // TODO validate 'javaPersistentTypes' + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java new file mode 100644 index 0000000000..a52f96ecf1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.java.JavaAssociationOverride; +import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaAssociationOverrideRelationshipReference; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaOverride; +import org.eclipse.jpt.core.resource.java.AssociationOverrideAnnotation; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaAssociationOverride extends AbstractJavaOverride + implements JavaAssociationOverride +{ + + protected final JavaAssociationOverrideRelationshipReference relationshipReference; + + public GenericJavaAssociationOverride(JavaAssociationOverrideContainer parent, JavaAssociationOverride.Owner owner) { + super(parent, owner); + this.relationshipReference = buildRelationshipReference(); + } + + public void initializeFrom(AssociationOverride oldAssociationOverride) { + this.setName(oldAssociationOverride.getName()); + this.relationshipReference.initializeFrom(oldAssociationOverride.getRelationshipReference()); + } + + protected JavaAssociationOverrideRelationshipReference buildRelationshipReference() { + return getJpaFactory().buildJavaAssociationOverrideRelationshipReference(this); + } + + public JavaAssociationOverrideRelationshipReference getRelationshipReference() { + return this.relationshipReference; + } + + @Override + public JavaAssociationOverride setVirtual(boolean virtual) { + return (JavaAssociationOverride) super.setVirtual(virtual); + } + + @Override + public AssociationOverrideAnnotation getOverrideAnnotation() { + return (AssociationOverrideAnnotation) super.getOverrideAnnotation(); + } + + @Override + public JavaAssociationOverride.Owner getOwner() { + return (JavaAssociationOverride.Owner) super.getOwner(); + } + + @Override + protected Iterator<String> candidateNames() { + return this.getOwner().allOverridableAttributeNames(); + } + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + result = this.relationshipReference.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + return null; + } + + public void initialize(AssociationOverrideAnnotation associationOverride) { + super.initialize(associationOverride); + this.relationshipReference.initialize(associationOverride); + } + + public void update(AssociationOverrideAnnotation associationOverride) { + super.update(associationOverride); + this.relationshipReference.update(associationOverride); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.relationshipReference.validate(messages, reporter, astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java new file mode 100644 index 0000000000..552a6aa8f7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java @@ -0,0 +1,445 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.RelationshipReference; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAssociationOverride; +import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.AssociationOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.AssociationOverridesAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.resource.java.NestableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaAssociationOverrideContainer extends AbstractJavaJpaContextNode + implements JavaAssociationOverrideContainer +{ + protected JavaResourcePersistentMember javaResourcePersistentMember; + + protected final JavaAssociationOverrideContainer.Owner owner; + + protected final List<JavaAssociationOverride> specifiedAssociationOverrides; + + protected final List<JavaAssociationOverride> virtualAssociationOverrides; + + public GenericJavaAssociationOverrideContainer(JavaJpaContextNode parent, JavaAssociationOverrideContainer.Owner owner) { + super(parent); + this.owner = owner; + this.specifiedAssociationOverrides = new ArrayList<JavaAssociationOverride>(); + this.virtualAssociationOverrides = new ArrayList<JavaAssociationOverride>(); + } + + protected Owner getOwner() { + return this.owner; + } + + public JavaAssociationOverride getAssociationOverrideNamed(String name) { + return (JavaAssociationOverride) getOverrideNamed(name, associationOverrides()); + } + + public boolean containsAssociationOverride(String name) { + return containsOverride(name, associationOverrides()); + } + + public boolean containsSpecifiedAssociationOverride(String name) { + return containsOverride(name, specifiedAssociationOverrides()); + } + + public boolean containsDefaultAssociationOverride(String name) { + return containsOverride(name, virtualAssociationOverrides()); + } + + protected BaseOverride getOverrideNamed(String name, ListIterator<? extends BaseOverride> overrides) { + for (BaseOverride override : CollectionTools.iterable(overrides)) { + String overrideName = override.getName(); + if (overrideName == null && name == null) { + return override; + } + if (overrideName != null && overrideName.equals(name)) { + return override; + } + } + return null; + } + + protected boolean containsOverride(String name, ListIterator<? extends BaseOverride> overrides) { + return getOverrideNamed(name, overrides) != null; + } + + protected Iterator<String> allOverridableAssociationNames() { + return getOwner().allOverridableNames(); + } + + @SuppressWarnings("unchecked") + public ListIterator<JavaAssociationOverride> associationOverrides() { + return new CompositeListIterator<JavaAssociationOverride>(specifiedAssociationOverrides(), virtualAssociationOverrides()); + } + + public int associationOverridesSize() { + return this.specifiedAssociationOverridesSize() + this.virtualAssociationOverridesSize(); + } + + public ListIterator<JavaAssociationOverride> virtualAssociationOverrides() { + return new CloneListIterator<JavaAssociationOverride>(this.virtualAssociationOverrides); + } + + public int virtualAssociationOverridesSize() { + return this.virtualAssociationOverrides.size(); + } + + public ListIterator<JavaAssociationOverride> specifiedAssociationOverrides() { + return new CloneListIterator<JavaAssociationOverride>(this.specifiedAssociationOverrides); + } + + public int specifiedAssociationOverridesSize() { + return this.specifiedAssociationOverrides.size(); + } + + public JavaAssociationOverride addSpecifiedAssociationOverride(int index) { + JavaAssociationOverride associationOverride = getJpaFactory().buildJavaAssociationOverride(this, createAssociationOverrideOwner()); + this.specifiedAssociationOverrides.add(index, associationOverride); + AssociationOverrideAnnotation associationOverrideResource = + (AssociationOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation( + index, AssociationOverrideAnnotation.ANNOTATION_NAME, + AssociationOverridesAnnotation.ANNOTATION_NAME); + associationOverride.initialize(associationOverrideResource); + this.fireItemAdded(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, index, associationOverride); + return associationOverride; + } + + protected JavaAssociationOverride.Owner createAssociationOverrideOwner() { + return new AssociationOverrideOwner(); + } + + protected void addSpecifiedAssociationOverride(int index, JavaAssociationOverride associationOverride) { + addItemToList(index, associationOverride, this.specifiedAssociationOverrides, SPECIFIED_ASSOCIATION_OVERRIDES_LIST); + } + + protected void addSpecifiedAssociationOverride(JavaAssociationOverride associationOverride) { + this.addSpecifiedAssociationOverride(this.specifiedAssociationOverrides.size(), associationOverride); + } + + protected void removeSpecifiedAssociationOverride_(JavaAssociationOverride associationOverride) { + removeItemFromList(associationOverride, this.specifiedAssociationOverrides, SPECIFIED_ASSOCIATION_OVERRIDES_LIST); + } + + public void moveSpecifiedAssociationOverride(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedAssociationOverrides, targetIndex, sourceIndex); + this.javaResourcePersistentMember.moveAnnotation( + targetIndex, sourceIndex, AssociationOverridesAnnotation.ANNOTATION_NAME); + fireItemMoved(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, targetIndex, sourceIndex); + } + + protected JavaAssociationOverride setAssociationOverrideVirtual(boolean virtual, JavaAssociationOverride associationOverride) { + // Add a new attribute override + if (virtual) { + return setAssociationOverrideVirtual(associationOverride); + } + return setAssociationOverrideSpecified(associationOverride); + } + + protected JavaAssociationOverride setAssociationOverrideVirtual(JavaAssociationOverride associationOverride) { + int index = this.specifiedAssociationOverrides.indexOf(associationOverride); + this.specifiedAssociationOverrides.remove(index); + String associationOverrideName = associationOverride.getName(); + //add the virtual attribute override so that I can control the order that change notification is sent. + //otherwise when we remove the annotation from java we will get an update and add the attribute override + //during the update. This causes the UI to be flaky, since change notification might not occur in the correct order + JavaAssociationOverride virtualAssociationOverride = null; + if (associationOverrideName != null) { + for (String name : CollectionTools.iterable(allOverridableAssociationNames())) { + if (name.equals(associationOverrideName)) { + //store the virtualAttributeOverride so we can fire change notification later + virtualAssociationOverride = buildVirtualAssociationOverride(name); + this.virtualAssociationOverrides.add(virtualAssociationOverride); + break; + } + } + } + + this.javaResourcePersistentMember.removeAnnotation( + index, AssociationOverrideAnnotation.ANNOTATION_NAME, + AssociationOverridesAnnotation.ANNOTATION_NAME); + fireItemRemoved(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, index, associationOverride); + + if (virtualAssociationOverride != null) { + fireItemAdded(VIRTUAL_ASSOCIATION_OVERRIDES_LIST, virtualAssociationOverridesSize() - 1, virtualAssociationOverride); + } + return virtualAssociationOverride; + } + + protected JavaAssociationOverride setAssociationOverrideSpecified(JavaAssociationOverride oldAssociationOverride) { + int index = specifiedAssociationOverridesSize(); + JavaAssociationOverride newAssociationOverride = getJpaFactory().buildJavaAssociationOverride(this, createAssociationOverrideOwner()); + this.specifiedAssociationOverrides.add(index, newAssociationOverride); + + AssociationOverrideAnnotation attributeOverrideResource = + (AssociationOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation( + index, AssociationOverrideAnnotation.ANNOTATION_NAME, + AssociationOverridesAnnotation.ANNOTATION_NAME); + newAssociationOverride.initialize(attributeOverrideResource); + + int virtualIndex = this.virtualAssociationOverrides.indexOf(oldAssociationOverride); + this.virtualAssociationOverrides.remove(virtualIndex); + + newAssociationOverride.initializeFrom(oldAssociationOverride); + + this.fireItemRemoved(VIRTUAL_ASSOCIATION_OVERRIDES_LIST, virtualIndex, oldAssociationOverride); + this.fireItemAdded(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, index, newAssociationOverride); + + return newAssociationOverride; + } + + protected void addVirtualAssociationOverride(JavaAssociationOverride associationOverride) { + addItemToList(associationOverride, this.virtualAssociationOverrides, VIRTUAL_ASSOCIATION_OVERRIDES_LIST); + } + + protected void removeVirtualAssociationOverride(JavaAssociationOverride associationOverride) { + removeItemFromList(associationOverride, this.virtualAssociationOverrides, VIRTUAL_ASSOCIATION_OVERRIDES_LIST); + } + + + + public void initialize(JavaResourcePersistentMember resourcePersistentMember) { + this.javaResourcePersistentMember = resourcePersistentMember; + this.initializeSpecifiedAssociationOverrides(); + this.initializeVirtualAssociationOverrides(); + } + + protected void initializeSpecifiedAssociationOverrides() { + for (Iterator<NestableAnnotation> stream = this.relavantResourceAssociationOverrides(); stream.hasNext(); ) { + this.specifiedAssociationOverrides.add( + buildAssociationOverride((AssociationOverrideAnnotation) stream.next())); + } + } + + protected void initializeVirtualAssociationOverrides() { + for (String name : CollectionTools.iterable(allOverridableAssociationNames())) { + JavaAssociationOverride associationOverride = getAssociationOverrideNamed(name); + if (associationOverride == null) { + this.virtualAssociationOverrides.add(buildVirtualAssociationOverride(name)); + } + } + } + + public void update(JavaResourcePersistentMember resourcePersistentMember) { + this.javaResourcePersistentMember = resourcePersistentMember; + this.updateSpecifiedAssociationOverrides(); + } + + @Override + public void postUpdate() { + super.postUpdate(); + + //In postUpdate because the joiningStrategy is not initialized on relationship mappings. + //if we fix the issue that we do not initialize java mappings, but they instead get initialized + //during the first update, then we can probably move this. + updateVirtualAssociationOverrides(); + } + + + protected void updateSpecifiedAssociationOverrides() { + ListIterator<JavaAssociationOverride> associationOverrides = specifiedAssociationOverrides(); + Iterator<NestableAnnotation> resourceAssociationOverrides = this.relavantResourceAssociationOverrides(); + + while (associationOverrides.hasNext()) { + JavaAssociationOverride associationOverride = associationOverrides.next(); + if (resourceAssociationOverrides.hasNext()) { + associationOverride.update((AssociationOverrideAnnotation) resourceAssociationOverrides.next()); + } + else { + removeSpecifiedAssociationOverride_(associationOverride); + } + } + + while (resourceAssociationOverrides.hasNext()) { + addSpecifiedAssociationOverride(buildAssociationOverride((AssociationOverrideAnnotation) resourceAssociationOverrides.next())); + } + } + protected Iterator<NestableAnnotation> relavantResourceAssociationOverrides() { + Iterator<NestableAnnotation> resourceAssociationOverrides = + this.javaResourcePersistentMember.annotations( + AssociationOverrideAnnotation.ANNOTATION_NAME, + AssociationOverridesAnnotation.ANNOTATION_NAME); + + return new FilteringIterator<NestableAnnotation>(resourceAssociationOverrides) { + @Override + protected boolean accept(NestableAnnotation o) { + String overrideName = ((AssociationOverrideAnnotation) o).getName(); + return overrideName != null && getOwner().isRelevant(overrideName); + } + }; + } + + + protected JavaAssociationOverride buildAssociationOverride(AssociationOverrideAnnotation associationOverrideResource) { + JavaAssociationOverride associationOverride = getJpaFactory().buildJavaAssociationOverride(this, createAssociationOverrideOwner()); + associationOverride.initialize(associationOverrideResource); + return associationOverride; + } + + protected JavaAssociationOverride buildVirtualAssociationOverride(String name) { + return buildAssociationOverride(buildVirtualAssociationOverrideAnnotation(name)); + } + + protected AssociationOverrideAnnotation buildVirtualAssociationOverrideAnnotation(String name) { + RelationshipReference relationshipReference = this.resolveAssociationOverrideRelationshipReference(name); + return getJpaFactory().buildJavaVirtualAssociationOverrideAnnotation(this.javaResourcePersistentMember, name, relationshipReference.getPredominantJoiningStrategy()); + } + + private RelationshipReference resolveAssociationOverrideRelationshipReference(String associationOverrideName) { + return getOwner().resolveRelationshipReference(associationOverrideName); + } + + protected void updateVirtualAssociationOverrides() { + for (String name : CollectionTools.iterable(allOverridableAssociationNames())) { + JavaAssociationOverride associationOverride = getAssociationOverrideNamed(name); + if (associationOverride == null) { + addVirtualAssociationOverride(buildVirtualAssociationOverride(name)); + } + else if (associationOverride.isVirtual()) { + associationOverride.update(buildVirtualAssociationOverrideAnnotation(name)); + } + } + + Collection<String> associationNames = CollectionTools.collection(allOverridableAssociationNames()); + + //remove any default mappings that are not included in the associationNames collection + for (JavaAssociationOverride associationOverride : CollectionTools.iterable(virtualAssociationOverrides())) { + if (!associationNames.contains(associationOverride.getName()) + || containsSpecifiedAssociationOverride(associationOverride.getName())) { + removeVirtualAssociationOverride(associationOverride); + } + } + } + + + //******************** Code Completion ************************* + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaAssociationOverride override : CollectionTools.iterable(this.associationOverrides())) { + result = override.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + //********** Validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + for (Iterator<JavaAssociationOverride> stream = this.associationOverrides(); stream.hasNext();) { + stream.next().validate(messages, reporter, astRoot); + } + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return getOwner().getValidationTextRange(astRoot); + } + + + // ********** association override owner ********** + + protected class AssociationOverrideOwner implements JavaAssociationOverride.Owner { + + public RelationshipMapping getRelationshipMapping(String attributeName) { + return MappingTools.getRelationshipMapping(attributeName, getOwner().getOverridableTypeMapping()); + } + + public boolean isVirtual(BaseOverride override) { + return GenericJavaAssociationOverrideContainer.this.virtualAssociationOverrides.contains(override); + } + + public BaseOverride setVirtual(boolean virtual, BaseOverride attributeOverride) { + return GenericJavaAssociationOverrideContainer.this.setAssociationOverrideVirtual(virtual, (JavaAssociationOverride) attributeOverride); + } + + public TypeMapping getTypeMapping() { + return getOwner().getTypeMapping(); + } + + public Iterator<String> allOverridableAttributeNames() { + return GenericJavaAssociationOverrideContainer.this.allOverridableAssociationNames(); + } + + public String getPossiblePrefix() { + return getOwner().getPossiblePrefix(); + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + public String getDefaultTableName() { + return getOwner().getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedReferencedColumnNameMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedReferencedColumnNameMessage(override, column, textRange); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(override, column, textRange); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(override, column, textRange); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideRelationshipReference.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideRelationshipReference.java new file mode 100644 index 0000000000..9c18c1ee73 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAssociationOverrideRelationshipReference.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.AssociationOverrideRelationshipReference; +import org.eclipse.jpt.core.context.JoiningStrategy; +import org.eclipse.jpt.core.context.java.JavaAssociationOverride; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaAssociationOverrideRelationshipReference; + +public class GenericJavaAssociationOverrideRelationshipReference extends AbstractJavaAssociationOverrideRelationshipReference +{ + + public GenericJavaAssociationOverrideRelationshipReference(JavaAssociationOverride parent) { + super(parent); + } + + public void initializeFrom(AssociationOverrideRelationshipReference oldAssociationOverride) { + if (oldAssociationOverride.getJoinColumnJoiningStrategy().hasSpecifiedJoinColumns()) { + getJoinColumnJoiningStrategy().initializeFrom(oldAssociationOverride.getJoinColumnJoiningStrategy()); + } + } + + @Override + protected JoiningStrategy calculatePredominantJoiningStrategy() { + return this.joinColumnJoiningStrategy; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java new file mode 100644 index 0000000000..9ccff4bc9d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java @@ -0,0 +1,254 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAttributeOverride; +import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaColumn; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaOverride; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.AttributeOverride2_0; +import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.jpt.core.resource.java.AttributeOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.ColumnAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaAttributeOverride + extends AbstractJavaOverride + implements AttributeOverride2_0, JavaAttributeOverride +{ + protected final JavaColumn column; + + /* 2.0 feature - a relationship may map this attribute override */ + protected boolean mappedByRelationship; + + + public GenericJavaAttributeOverride( + JavaAttributeOverrideContainer parent, + JavaAttributeOverride.Owner owner) { + + super(parent, owner); + this.column = getJpaFactory().buildJavaColumn(this, this); + } + + + @Override + public JavaAttributeOverride setVirtual(boolean virtual) { + return (JavaAttributeOverride) super.setVirtual(virtual); + } + + @Override + public AttributeOverrideAnnotation getOverrideAnnotation() { + return (AttributeOverrideAnnotation) super.getOverrideAnnotation(); + } + + @Override + public JavaAttributeOverride.Owner getOwner() { + return (JavaAttributeOverride.Owner) super.getOwner(); + } + + public ColumnAnnotation getResourceColumn() { + return this.getOverrideAnnotation().getNonNullColumn(); + } + + public ColumnAnnotation getResourceColumnOrNull() { + return this.getOverrideAnnotation().getColumn(); + } + + protected boolean isColumnSpecified() { + return getResourceColumn() != null; + } + + + //************* NamedColumn.Owner implementation ************** + + public TypeMapping getTypeMapping() { + return this.getOwner().getTypeMapping(); + } + + public Table getDbTable(String tableName) { + return this.getOwner().getDbTable(tableName); + } + + public String getDefaultColumnName() { + Column column = resolveOverriddenColumn(); + if (column == null) { + return getName(); + } + return column.getName(); + } + + + //************* BaseColumn.Owner implementation ************** + + public String getDefaultTableName() { + Column column = resolveOverriddenColumn(); + if (column != null) { + String tableName = column.getSpecifiedTable(); + if (tableName != null) { + return tableName; + } + } + return getOwner().getDefaultTableName(); + } + + protected Column resolveOverriddenColumn() { + return isVirtual() ? getOwner().resolveOverriddenColumn(getName()) : null; + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + + //************* AttributeOverride implementation ************** + + public JavaColumn getColumn() { + return this.column; + } + + + //************* JavaOverride implementation ************** + + @Override + protected Iterator<String> candidateNames() { + return this.getOwner().allOverridableAttributeNames(); + } + + + // **************** AttributeOverride2_0 impl ***************************** + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean newValue) { + boolean oldValue = this.mappedByRelationship; + this.mappedByRelationship = newValue; + firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, oldValue, newValue); + } + + protected boolean calculateMappedByRelationship() { + for (SingleRelationshipMapping2_0 each : getMapsIdRelationships()) { + if (getName() == null) { + return false; + } + + // overrideable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + String qualifier = + (getName().indexOf('.') > 0) ? + getName().substring(0, getName().indexOf('.')) + : getName(); + return qualifier.equals(each.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue()); + } + return false; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + //************* java resource model -> java context model ************** + + public void initialize(AttributeOverrideAnnotation attributeOverrideResource) { + super.initialize(attributeOverrideResource); + this.column.initialize(this.getResourceColumn()); + this.mappedByRelationship = calculateMappedByRelationship(); + } + + public void update(AttributeOverrideAnnotation attributeOverrideResource) { + super.update(attributeOverrideResource); + this.column.update(this.getResourceColumn()); + setMappedByRelationship(calculateMappedByRelationship()); + } + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + result = this.getColumn().javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + return null; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + // [JPA 2.0] if the column is specified, or if the override is not mapped by a relationship, + // then the column is validated. + // (In JPA 1.0, the column will always be validated, since the override is never mapped by a + // relationship) + if (isColumnSpecified() || ! isMappedByRelationship()) { + getColumn().validate(messages, reporter, astRoot); + } + + // [JPA 2.0] if the override is mapped by a relationship, then that actually is in itself + // a validation error + // (We prevent implied overrides that are mapped by a relationship ... hopefully) + // (In JPA 1.0, this will never occur) + if (isMappedByRelationship()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ATTRIBUTE_OVERRIDE_MAPPED_BY_RELATIONSHIP_AND_SPECIFIED, + new String[] {}, + this, + getValidationTextRange(astRoot))); + } + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(this, column, textRange); + } + + public IMessage buildTableNotValidMessage(BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(this, column, textRange); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java new file mode 100644 index 0000000000..027151e02d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java @@ -0,0 +1,451 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAttributeOverride; +import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.java.VirtualAttributeOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.Annotation; +import org.eclipse.jpt.core.resource.java.AttributeOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.AttributeOverridesAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.resource.java.NestableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaAttributeOverrideContainer extends AbstractJavaJpaContextNode + implements JavaAttributeOverrideContainer +{ + protected JavaResourcePersistentMember javaResourcePersistentMember; + + protected final List<JavaAttributeOverride> specifiedAttributeOverrides; + + protected final List<JavaAttributeOverride> virtualAttributeOverrides; + + protected final Owner owner; + + public GenericJavaAttributeOverrideContainer(JavaJpaContextNode parent, Owner owner) { + super(parent); + this.owner = owner; + this.specifiedAttributeOverrides = new ArrayList<JavaAttributeOverride>(); + this.virtualAttributeOverrides = new ArrayList<JavaAttributeOverride>(); + } + + protected Owner getOwner() { + return this.owner; + } + + @SuppressWarnings("unchecked") + public ListIterator<JavaAttributeOverride> attributeOverrides() { + return new CompositeListIterator<JavaAttributeOverride>(specifiedAttributeOverrides(), virtualAttributeOverrides()); + } + + public int attributeOverridesSize() { + return this.specifiedAttributeOverridesSize() + this.virtualAttributeOverridesSize(); + } + + public ListIterator<JavaAttributeOverride> virtualAttributeOverrides() { + return new CloneListIterator<JavaAttributeOverride>(this.virtualAttributeOverrides); + } + + public int virtualAttributeOverridesSize() { + return this.virtualAttributeOverrides.size(); + } + + public ListIterator<JavaAttributeOverride> specifiedAttributeOverrides() { + return new CloneListIterator<JavaAttributeOverride>(this.specifiedAttributeOverrides); + } + + public int specifiedAttributeOverridesSize() { + return this.specifiedAttributeOverrides.size(); + } + + protected JavaAttributeOverride addSpecifiedAttributeOverride(int index) { + JavaAttributeOverride attributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner()); + this.specifiedAttributeOverrides.add(index, attributeOverride); + AttributeOverrideAnnotation attributeOverrideResource = + (AttributeOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation( + index, AttributeOverrideAnnotation.ANNOTATION_NAME, + AttributeOverridesAnnotation.ANNOTATION_NAME); + attributeOverride.initialize(attributeOverrideResource); + this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, attributeOverride); + return attributeOverride; + } + + protected JavaAttributeOverride setAttributeOverrideVirtual(boolean virtual, JavaAttributeOverride attributeOverride) { + // Add a new attribute override + if (virtual) { + return setAttributeOverrideVirtual(attributeOverride); + } + return setAttributeOverrideSpecified(attributeOverride); + } + + protected JavaAttributeOverride setAttributeOverrideVirtual(JavaAttributeOverride specifiedAttributeOverride) { + int index = this.specifiedAttributeOverrides.indexOf(specifiedAttributeOverride); + this.specifiedAttributeOverrides.remove(index); + String attributeOverrideName = specifiedAttributeOverride.getName(); + //add the virtual attribute override so that I can control the order that change notification is sent. + //otherwise when we remove the annotation from java we will get an update and add the attribute override + //during the update. This causes the UI to be flaky, since change notification might not occur in the correct order + JavaAttributeOverride virtualAttributeOverride = null; + if (attributeOverrideName != null) { + for (String name : CollectionTools.iterable(allOverridableAttributeNames())) { + if (name.equals(attributeOverrideName)) { + //store the virtualAttributeOverride so we can fire change notification later + virtualAttributeOverride = buildVirtualAttributeOverride(name); + this.virtualAttributeOverrides.add(virtualAttributeOverride); + break; + } + } + } + + this.javaResourcePersistentMember.removeAnnotation( + this.resourceIndexOf(specifiedAttributeOverride), + AttributeOverrideAnnotation.ANNOTATION_NAME, + AttributeOverridesAnnotation.ANNOTATION_NAME); + fireItemRemoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, specifiedAttributeOverride); + + if (virtualAttributeOverride != null) { + fireItemAdded(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, virtualAttributeOverridesSize() - 1, virtualAttributeOverride); + } + return virtualAttributeOverride; + } + + protected JavaAttributeOverride setAttributeOverrideSpecified(JavaAttributeOverride virtualAttributeOverride) { + int index = specifiedAttributeOverridesSize(); + int resourceIndex = 0; + if (specifiedAttributeOverridesSize() > 0) { + resourceIndex = this.resourceIndexOf(this.specifiedAttributeOverrides.get(index - 1)) + 1; + } + JavaAttributeOverride specifiedAttributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner()); + + AttributeOverrideAnnotation attributeOverrideResource = + (AttributeOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation( + resourceIndex, + AttributeOverrideAnnotation.ANNOTATION_NAME, + AttributeOverridesAnnotation.ANNOTATION_NAME); + specifiedAttributeOverride.initialize(attributeOverrideResource); + + int defaultIndex = this.virtualAttributeOverrides.indexOf(virtualAttributeOverride); + this.virtualAttributeOverrides.remove(defaultIndex); + + String name = virtualAttributeOverride.getName(); + String prefix = getOwner().getWritePrefix(); + if (prefix != null) { + name = prefix + name; + } + this.specifiedAttributeOverrides.add(index, specifiedAttributeOverride); + specifiedAttributeOverride.setName(name); + specifiedAttributeOverride.getColumn().setSpecifiedName(virtualAttributeOverride.getColumn().getName()); + + this.fireItemRemoved(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, defaultIndex, virtualAttributeOverride); + this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, specifiedAttributeOverride); + + return specifiedAttributeOverride; + } + + protected JavaAttributeOverride.Owner createAttributeOverrideOwner() { + return new AttributeOverrideOwner(); + } + + protected void addSpecifiedAttributeOverride(int index, JavaAttributeOverride attributeOverride) { + addItemToList(index, attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST); + } + + protected void addSpecifiedAttributeOverride(JavaAttributeOverride attributeOverride) { + this.addSpecifiedAttributeOverride(this.specifiedAttributeOverrides.size(), attributeOverride); + } + + protected void removeSpecifiedAttributeOverride_(JavaAttributeOverride attributeOverride) { + removeItemFromList(attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST); + } + + public void moveSpecifiedAttributeOverride(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedAttributeOverrides, targetIndex, sourceIndex); + this.javaResourcePersistentMember.moveAnnotation( + targetIndex, sourceIndex, AttributeOverridesAnnotation.ANNOTATION_NAME); + fireItemMoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, targetIndex, sourceIndex); + } + + protected void addVirtualAttributeOverride(JavaAttributeOverride attributeOverride) { + addItemToList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST); + } + + protected void removeVirtualAttributeOverride(JavaAttributeOverride attributeOverride) { + removeItemFromList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST); + } + + public JavaAttributeOverride getAttributeOverrideNamed(String name) { + return (JavaAttributeOverride) getOverrideNamed(name, attributeOverrides()); + } + + public boolean containsAttributeOverride(String name) { + return containsOverride(name, attributeOverrides()); + } + + public boolean containsDefaultAttributeOverride(String name) { + return containsOverride(name, virtualAttributeOverrides()); + } + + public boolean containsSpecifiedAttributeOverride(String name) { + return containsOverride(name, specifiedAttributeOverrides()); + } + + protected BaseOverride getOverrideNamed(String name, ListIterator<? extends BaseOverride> overrides) { + for (BaseOverride override : CollectionTools.iterable(overrides)) { + String overrideName = override.getName(); + if (overrideName == null && name == null) { + return override; + } + if (overrideName != null && overrideName.equals(name)) { + return override; + } + } + return null; + } + + protected boolean containsOverride(String name, ListIterator<? extends BaseOverride> overrides) { + return getOverrideNamed(name, overrides) != null; + } + + protected Iterator<String> allOverridableAttributeNames() { + return getOwner().allOverridableNames(); + } + + public void initialize(JavaResourcePersistentMember resourcePersistentMember) { + this.javaResourcePersistentMember = resourcePersistentMember; + this.initializeSpecifiedAttributeOverrides(); + this.initializeVirtualAttributeOverrides(); + } + + protected void initializeSpecifiedAttributeOverrides() { + for (Iterator<NestableAnnotation> stream = this.relavantResourceAttributeOverrides(); stream.hasNext(); ) { + this.specifiedAttributeOverrides.add( + buildAttributeOverride((AttributeOverrideAnnotation) stream.next())); + } + } + + protected void initializeVirtualAttributeOverrides() { + for (String name : CollectionTools.iterable(allOverridableAttributeNames())) { + JavaAttributeOverride attributeOverride = getAttributeOverrideNamed(name); + if (attributeOverride == null) { + this.virtualAttributeOverrides.add(buildVirtualAttributeOverride(name)); + } + } + } + + public void update(JavaResourcePersistentMember resourcePersistentMember) { + this.javaResourcePersistentMember = resourcePersistentMember; + this.updateSpecifiedAttributeOverrides(); + this.updateVirtualAttributeOverrides(); + } + + protected void updateSpecifiedAttributeOverrides() { + ListIterator<JavaAttributeOverride> attributeOverrides = specifiedAttributeOverrides(); + Iterator<NestableAnnotation> resourceAttributeOverrides = this.relavantResourceAttributeOverrides(); + + while (attributeOverrides.hasNext()) { + JavaAttributeOverride attributeOverride = attributeOverrides.next(); + if (resourceAttributeOverrides.hasNext()) { + attributeOverride.update((AttributeOverrideAnnotation) resourceAttributeOverrides.next()); + } + else { + removeSpecifiedAttributeOverride_(attributeOverride); + } + } + + while (resourceAttributeOverrides.hasNext()) { + addSpecifiedAttributeOverride(buildAttributeOverride((AttributeOverrideAnnotation) resourceAttributeOverrides.next())); + } + } + + protected Iterator<NestableAnnotation> relavantResourceAttributeOverrides() { + Iterator<NestableAnnotation> resourceAttributeOverrides = + this.javaResourcePersistentMember.annotations( + AttributeOverrideAnnotation.ANNOTATION_NAME, + AttributeOverridesAnnotation.ANNOTATION_NAME); + + return new FilteringIterator<NestableAnnotation>(resourceAttributeOverrides) { + @Override + protected boolean accept(NestableAnnotation o) { + String overrideName = ((AttributeOverrideAnnotation) o).getName(); + return overrideName != null && getOwner().isRelevant(overrideName); + } + }; + } + + protected int resourceIndexOf(JavaAttributeOverride specifiedAttributeOverride) { + Iterator<NestableAnnotation> overrideAnnotations = this.javaResourcePersistentMember.annotations( + AttributeOverrideAnnotation.ANNOTATION_NAME, + AttributeOverridesAnnotation.ANNOTATION_NAME); + + return CollectionTools.indexOf( + overrideAnnotations, + specifiedAttributeOverride.getOverrideAnnotation()); + } + + protected JavaAttributeOverride buildAttributeOverride(AttributeOverrideAnnotation attributeOverrideResource) { + JavaAttributeOverride attributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner()); + attributeOverride.initialize(attributeOverrideResource); + return attributeOverride; + } + + protected JavaAttributeOverride buildVirtualAttributeOverride(String attributeOverrideName) { + return buildAttributeOverride(buildVirtualAttributeOverrideAnnotation(attributeOverrideName)); + } + + protected VirtualAttributeOverrideAnnotation buildVirtualAttributeOverrideAnnotation(String attributeOverrideName) { + Column column = resolveOverriddenColumn(attributeOverrideName); + return new VirtualAttributeOverrideAnnotation(this.javaResourcePersistentMember, attributeOverrideName, column); + } + + private Column resolveOverriddenColumn(String attributeOverrideName) { + return getOwner().resolveOverriddenColumn(attributeOverrideName); + } + + protected void updateVirtualAttributeOverrides() { + for (String name : CollectionTools.iterable(allOverridableAttributeNames())) { + JavaAttributeOverride attributeOverride = getAttributeOverrideNamed(name); + if (attributeOverride == null) { + addVirtualAttributeOverride(buildVirtualAttributeOverride(name)); + } + else if (attributeOverride.isVirtual()) { + attributeOverride.update(buildVirtualAttributeOverrideAnnotation(name)); + } + } + + Collection<String> attributeNames = CollectionTools.collection(allOverridableAttributeNames()); + + //remove any default mappings that are not included in the attributeNames collection + for (JavaAttributeOverride attributeOverride : CollectionTools.iterable(virtualAttributeOverrides())) { + if (!attributeNames.contains(attributeOverride.getName()) + || containsSpecifiedAttributeOverride(attributeOverride.getName())) { + removeVirtualAttributeOverride(attributeOverride); + } + } + } + + + //******************** Code Completion ************************* + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaAttributeOverride override : CollectionTools.iterable(this.attributeOverrides())) { + result = override.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + //********** Validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + for (Iterator<JavaAttributeOverride> stream = this.attributeOverrides(); stream.hasNext();) { + stream.next().validate(messages, reporter, astRoot); + } + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + Annotation annotation = + this.javaResourcePersistentMember.getAnnotation(AttributeOverridesAnnotation.ANNOTATION_NAME); + if (annotation == null) { + annotation = this.javaResourcePersistentMember.getAnnotation(AttributeOverrideAnnotation.ANNOTATION_NAME); + } + + return (annotation == null) ? + getOwner().getValidationTextRange(astRoot) + : annotation.getTextRange(astRoot); + } + + + // ********** attribute override owner ********** + + protected class AttributeOverrideOwner implements JavaAttributeOverride.Owner { + + public Column resolveOverriddenColumn(String attributeName) { + if (attributeName == null) { + return null; + } + return GenericJavaAttributeOverrideContainer.this.resolveOverriddenColumn(attributeName); + } + + public boolean isVirtual(BaseOverride override) { + return GenericJavaAttributeOverrideContainer.this.virtualAttributeOverrides.contains(override); + } + + public BaseOverride setVirtual(boolean virtual, BaseOverride attributeOverride) { + return GenericJavaAttributeOverrideContainer.this.setAttributeOverrideVirtual(virtual, (JavaAttributeOverride) attributeOverride); + } + + public TypeMapping getTypeMapping() { + return getOwner().getTypeMapping(); + } + + public Iterator<String> allOverridableAttributeNames() { + return GenericJavaAttributeOverrideContainer.this.allOverridableAttributeNames(); + } + + public String getPossiblePrefix() { + return getOwner().getPossiblePrefix(); + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + public String getDefaultTableName() { + return getOwner().getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(override, column, textRange); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaBasicMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaBasicMapping.java new file mode 100644 index 0000000000..9d6fa7b60d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaBasicMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaBasicMapping; + + +public class GenericJavaBasicMapping extends AbstractJavaBasicMapping +{ + public GenericJavaBasicMapping(JavaPersistentAttribute parent) { + super(parent); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaCascade.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaCascade.java new file mode 100644 index 0000000000..a9407bb495 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaCascade.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Cascade; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.jpa2.context.Cascade2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaCascade2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaRelationshipMapping2_0; +import org.eclipse.jpt.core.jpa2.resource.java.RelationshipMapping2_0Annotation; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaCascade + extends AbstractJavaJpaContextNode + implements JavaCascade2_0 +{ + protected boolean all; + + protected boolean persist; + + protected boolean merge; + + protected boolean remove; + + protected boolean refresh; + + /* JPA 2.0 */ + protected boolean detach; + + + public GenericJavaCascade(JavaRelationshipMapping2_0 parent) { + super(parent); + } + + + protected JavaRelationshipMapping2_0 getMapping() { + return (JavaRelationshipMapping2_0) getParent(); + } + + protected RelationshipMapping2_0Annotation getAnnotation() { + return getMapping().getMappingAnnotation(); + } + + public boolean isAll() { + return this.all; + } + + public void setAll(boolean newAll) { + boolean oldAll = this.all; + this.all = newAll; + getAnnotation().setCascadeAll(newAll); + firePropertyChanged(Cascade.ALL_PROPERTY, oldAll, newAll); + } + + protected void setAll_(boolean newAll) { + boolean oldAll = this.all; + this.all = newAll; + firePropertyChanged(Cascade.ALL_PROPERTY, oldAll, newAll); + } + + public boolean isPersist() { + return this.persist; + } + + public void setPersist(boolean newPersist) { + boolean oldPersist = this.persist; + this.persist = newPersist; + getAnnotation().setCascadePersist(newPersist); + firePropertyChanged(Cascade.PERSIST_PROPERTY, oldPersist, newPersist); + } + + protected void setPersist_(boolean newPersist) { + boolean oldPersist = this.persist; + this.persist = newPersist; + firePropertyChanged(Cascade.PERSIST_PROPERTY, oldPersist, newPersist); + } + + public boolean isMerge() { + return this.merge; + } + + public void setMerge(boolean newMerge) { + boolean oldMerge = this.merge; + this.merge = newMerge; + getAnnotation().setCascadeMerge(newMerge); + firePropertyChanged(Cascade.MERGE_PROPERTY, oldMerge, newMerge); + } + + protected void setMerge_(boolean newMerge) { + boolean oldMerge = this.merge; + this.merge = newMerge; + firePropertyChanged(Cascade.MERGE_PROPERTY, oldMerge, newMerge); + } + + public boolean isRemove() { + return this.remove; + } + + public void setRemove(boolean newRemove) { + boolean oldRemove = this.remove; + this.remove = newRemove; + getAnnotation().setCascadeRemove(newRemove); + firePropertyChanged(Cascade.REMOVE_PROPERTY, oldRemove, newRemove); + } + + protected void setRemove_(boolean newRemove) { + boolean oldRemove = this.remove; + this.remove = newRemove; + firePropertyChanged(Cascade.REMOVE_PROPERTY, oldRemove, newRemove); + } + + public boolean isRefresh() { + return this.refresh; + } + + public void setRefresh(boolean newRefresh) { + boolean oldRefresh = this.refresh; + this.refresh = newRefresh; + getAnnotation().setCascadeRefresh(newRefresh); + firePropertyChanged(Cascade.REFRESH_PROPERTY, oldRefresh, newRefresh); + } + + protected void setRefresh_(boolean newRefresh) { + boolean oldRefresh = this.refresh; + this.refresh = newRefresh; + firePropertyChanged(Cascade.REFRESH_PROPERTY, oldRefresh, newRefresh); + } + + public boolean isDetach() { + return this.detach; + } + + public void setDetach(boolean newDetach) { + boolean oldDetach = this.detach; + this.detach = newDetach; + getAnnotation().setCascadeDetach(newDetach); + firePropertyChanged(Cascade2_0.DETACH_PROPERTY, oldDetach, newDetach); + } + + protected void setDetach_(boolean newDetach) { + boolean oldDetach = this.detach; + this.detach = newDetach; + firePropertyChanged(Cascade2_0.DETACH_PROPERTY, oldDetach, newDetach); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return getAnnotation().getCascadeTextRange(astRoot); + } + + public void initialize() { + this.all = getAnnotation().isCascadeAll(); + this.persist = getAnnotation().isCascadePersist(); + this.merge = getAnnotation().isCascadeMerge(); + this.remove = getAnnotation().isCascadeRemove(); + this.refresh = getAnnotation().isCascadeRefresh(); + this.detach = getAnnotation().isCascadeDetach(); + } + + public void update() { + this.setAll_(getAnnotation().isCascadeAll()); + this.setPersist_(getAnnotation().isCascadePersist()); + this.setMerge_(getAnnotation().isCascadeMerge()); + this.setRemove_(getAnnotation().isCascadeRemove()); + this.setRefresh_(getAnnotation().isCascadeRefresh()); + this.setDetach_(getAnnotation().isCascadeDetach()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaColumn.java new file mode 100644 index 0000000000..170a03c628 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaColumn.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.java.JavaBaseColumn; +import org.eclipse.jpt.core.context.java.JavaColumn; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaBaseColumn; +import org.eclipse.jpt.core.resource.java.ColumnAnnotation; + +public class GenericJavaColumn extends AbstractJavaBaseColumn<ColumnAnnotation> implements JavaColumn +{ + + protected Integer specifiedLength; + + protected Integer specifiedPrecision; + + protected Integer specifiedScale; + + public GenericJavaColumn(JavaJpaContextNode parent, JavaBaseColumn.Owner owner) { + super(parent, owner); + } + + @Override + public void initialize(ColumnAnnotation column) { + super.initialize(column); + this.specifiedLength = this.getResourceLength(); + this.specifiedPrecision = this.getResourcePrecision(); + this.specifiedScale = this.getResourceScale(); + } + + @Override + public void update(ColumnAnnotation column) { + super.update(column); + this.setSpecifiedLength_(this.getResourceLength()); + this.setSpecifiedPrecision_(this.getResourcePrecision()); + this.setSpecifiedScale_(this.getResourceScale()); + } + + public int getLength() { + return (this.getSpecifiedLength() == null) ? getDefaultLength() : this.getSpecifiedLength().intValue(); + } + + public int getDefaultLength() { + return Column.DEFAULT_LENGTH; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + getResourceColumn().setLength(newSpecifiedLength); + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + protected void setSpecifiedLength_(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + protected Integer getResourceLength() { + return getResourceColumn().getLength(); + } + + public int getPrecision() { + return (this.getSpecifiedPrecision() == null) ? getDefaultPrecision() : this.getSpecifiedPrecision().intValue(); + } + + public int getDefaultPrecision() { + return Column.DEFAULT_PRECISION; + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + public void setSpecifiedPrecision(Integer newSpecifiedPrecision) { + Integer oldSpecifiedPrecision = this.specifiedPrecision; + this.specifiedPrecision = newSpecifiedPrecision; + getResourceColumn().setPrecision(newSpecifiedPrecision); + firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, oldSpecifiedPrecision, newSpecifiedPrecision); + } + + protected void setSpecifiedPrecision_(Integer newSpecifiedPrecision) { + Integer oldSpecifiedPrecision = this.specifiedPrecision; + this.specifiedPrecision = newSpecifiedPrecision; + firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, oldSpecifiedPrecision, newSpecifiedPrecision); + } + + protected Integer getResourcePrecision() { + return getResourceColumn().getPrecision(); + } + + public int getScale() { + return (this.getSpecifiedScale() == null) ? getDefaultScale() : this.getSpecifiedScale().intValue(); + } + + public int getDefaultScale() { + return Column.DEFAULT_SCALE; + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + public void setSpecifiedScale(Integer newSpecifiedScale) { + Integer oldSpecifiedScale = this.specifiedScale; + this.specifiedScale = newSpecifiedScale; + getResourceColumn().setScale(newSpecifiedScale); + firePropertyChanged(SPECIFIED_SCALE_PROPERTY, oldSpecifiedScale, newSpecifiedScale); + } + + protected void setSpecifiedScale_(Integer newSpecifiedScale) { + Integer oldSpecifiedScale = this.specifiedScale; + this.specifiedScale = newSpecifiedScale; + firePropertyChanged(SPECIFIED_SCALE_PROPERTY, oldSpecifiedScale, newSpecifiedScale); + } + + protected Integer getResourceScale() { + return getResourceColumn().getScale(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java new file mode 100644 index 0000000000..479a3fd7fe --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.DiscriminatorColumn; +import org.eclipse.jpt.core.context.DiscriminatorType; +import org.eclipse.jpt.core.context.java.JavaDiscriminatorColumn; +import org.eclipse.jpt.core.context.java.JavaEntity; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaNamedColumn; +import org.eclipse.jpt.core.resource.java.DiscriminatorColumnAnnotation; + +public class GenericJavaDiscriminatorColumn extends AbstractJavaNamedColumn<DiscriminatorColumnAnnotation> + implements JavaDiscriminatorColumn +{ + + protected DiscriminatorType specifiedDiscriminatorType; + + protected DiscriminatorType defaultDiscriminatorType; + + protected Integer specifiedLength; + + protected int defaultLength; + + public GenericJavaDiscriminatorColumn(JavaEntity parent, JavaDiscriminatorColumn.Owner owner) { + super(parent, owner); + } + + @Override + public void initialize(DiscriminatorColumnAnnotation column) { + super.initialize(column); + this.defaultDiscriminatorType = this.buildDefaultDiscriminatorType(); + this.defaultLength = this.buildDefaultLength(); + this.specifiedDiscriminatorType = this.getResourceDiscriminatorType(); + this.specifiedLength = this.getResourceLength(); + } + + @Override + public JavaDiscriminatorColumn.Owner getOwner() { + return (JavaDiscriminatorColumn.Owner) super.getOwner(); + } + + public boolean isResourceSpecified() { + return getResourceColumn().isSpecified(); + } + + public DiscriminatorType getDiscriminatorType() { + return (this.getSpecifiedDiscriminatorType() == null) ? this.getDefaultDiscriminatorType() : this.getSpecifiedDiscriminatorType(); + } + + public DiscriminatorType getDefaultDiscriminatorType() { + return this.defaultDiscriminatorType; + } + + protected void setDefaultDiscriminatorType(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.defaultDiscriminatorType; + this.defaultDiscriminatorType = discriminatorType; + firePropertyChanged(DEFAULT_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + public DiscriminatorType getSpecifiedDiscriminatorType() { + return this.specifiedDiscriminatorType; + } + + public void setSpecifiedDiscriminatorType(DiscriminatorType newSpecifiedDiscriminatorType) { + DiscriminatorType oldDiscriminatorType = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = newSpecifiedDiscriminatorType; + getResourceColumn().setDiscriminatorType(DiscriminatorType.toJavaResourceModel(newSpecifiedDiscriminatorType)); + firePropertyChanged(DiscriminatorColumn.SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, oldDiscriminatorType, newSpecifiedDiscriminatorType); + } + + /** + * internal setter used only for updating from the resource model. + * There were problems with InvalidThreadAccess exceptions in the UI + * when you set a value from the UI and the annotation doesn't exist yet. + * Adding the annotation causes an update to occur and then the exception. + */ + protected void setSpecifiedDiscriminatorType_(DiscriminatorType newSpecifiedDiscriminatorType) { + DiscriminatorType oldDiscriminatorType = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = newSpecifiedDiscriminatorType; + firePropertyChanged(DiscriminatorColumn.SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, oldDiscriminatorType, newSpecifiedDiscriminatorType); + } + + public int getLength() { + return (this.getSpecifiedLength() == null) ? this.getDefaultLength() : this.getSpecifiedLength().intValue(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int defaultLength) { + int old = this.defaultLength; + this.defaultLength = defaultLength; + firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, defaultLength); + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + getResourceColumn().setLength(newSpecifiedLength); + firePropertyChanged(DiscriminatorColumn.SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + /** + * internal setter used only for updating from the resource model. + * There were problems with InvalidThreadAccess exceptions in the UI + * when you set a value from the UI and the annotation doesn't exist yet. + * Adding the annotation causes an update to occur and then the exception. + */ + protected void setSpecifiedLength_(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + firePropertyChanged(DiscriminatorColumn.SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + + // ********** java annotations -> persistence model ********** + + @Override + public void update(DiscriminatorColumnAnnotation discriminatorColumn) { + //don't call super because postUpdate() handles updating the default column name + this.resourceColumn = discriminatorColumn; + this.setSpecifiedName_(discriminatorColumn.getName()); + this.setColumnDefinition_(discriminatorColumn.getColumnDefinition()); + this.setSpecifiedDiscriminatorType_(this.getResourceDiscriminatorType()); + this.setSpecifiedLength_(this.getResourceLength()); + } + + @Override + /** + * Using postUpdate since these defaults are dependent on the entity hierarchy + */ + public void postUpdate() { + super.postUpdate(); + this.setDefaultName(this.buildDefaultName()); + this.setDefaultDiscriminatorType(this.buildDefaultDiscriminatorType()); + this.setDefaultLength(this.buildDefaultLength()); + } + + protected DiscriminatorType getResourceDiscriminatorType() { + return DiscriminatorType.fromJavaResourceModel(getResourceColumn().getDiscriminatorType()); + } + + protected Integer getResourceLength() { + return getResourceColumn().getLength(); + } + + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + protected int buildDefaultLength() { + return this.getOwner().getDefaultLength(); + } + + protected DiscriminatorType buildDefaultDiscriminatorType() { + return this.getOwner().getDefaultDiscriminatorType(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddable.java new file mode 100644 index 0000000000..38a2c98167 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddable.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaEmbeddable; +import org.eclipse.jpt.utility.internal.ArrayTools; + + +public class GenericJavaEmbeddable + extends AbstractJavaEmbeddable +{ + public GenericJavaEmbeddable(JavaPersistentType parent) { + super(parent); + } + + @Override + public boolean attributeMappingKeyAllowed(String attributeMappingKey) { + //generic only allows basic and transient within an Embeddable + return ArrayTools.contains(ALLOWED_ATTRIBUTE_MAPPING_KEYS, attributeMappingKey); + } + + public static final String[] ALLOWED_ATTRIBUTE_MAPPING_KEYS = + new String[] { + MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY, + MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY + }; +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java new file mode 100644 index 0000000000..6b4045decb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaEmbeddedIdMapping; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaBaseEmbeddedMapping; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.EmbeddedIdMapping2_0; +import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.jpt.core.resource.java.EmbeddedIdAnnotation; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper; +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.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaEmbeddedIdMapping + extends AbstractJavaBaseEmbeddedMapping<EmbeddedIdAnnotation> + implements EmbeddedIdMapping2_0, JavaEmbeddedIdMapping +{ + /* 2.0 feature - a relationship may map this embedded id */ + protected boolean mappedByRelationship; + + + public GenericJavaEmbeddedIdMapping(JavaPersistentAttribute parent) { + super(parent); + } + + + //****************** JavaAttributeMapping implementation ******************* + + public String getKey() { + return MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY; + } + + public String getAnnotationName() { + return EmbeddedIdAnnotation.ANNOTATION_NAME; + } + + + // **************** EmbeddedId2_0 impl ************************************ + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean newValue) { + boolean oldValue = this.mappedByRelationship; + this.mappedByRelationship = newValue; + firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, oldValue, newValue); + } + + protected boolean calculateMappedByRelationship() { + for (SingleRelationshipMapping2_0 each : getMapsIdRelationships()) { + if (getName().equals(each.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue())) { + return true; + } + } + return false; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** overrides ********************************************* + + @Override + protected Iterator<String> embeddableOverrideableAttributeMappingNames() { + return (isMappedByRelationship()) ? + EmptyIterator.<String>instance() + : super.embeddableOverrideableAttributeMappingNames(); + } + + @Override + protected JavaAttributeOverrideContainer.Owner buildAttributeOverrideContainerOwner() { + return new AttributeOverrideContainerOwner(); + } + + + protected class AttributeOverrideContainerOwner + extends AbstractJavaBaseEmbeddedMapping.AttributeOverrideContainerOwner + { + @Override + public Iterator<String> allOverridableNames() { + return (GenericJavaEmbeddedIdMapping.this.isMappedByRelationship()) ? + EmptyIterator.<String>instance() + : super.allOverridableNames(); + } + + @Override + protected Iterator<String> allOverridableAttributeNames_(TypeMapping typeMapping) { + final Collection<String> mappedByRelationshipAttributes = CollectionTools.collection( + new TransformationIterator<SingleRelationshipMapping2_0, String>(getMapsIdRelationships()) { + @Override + protected String transform(SingleRelationshipMapping2_0 next) { + return next.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue(); + } + }); + return new FilteringIterator<String>(super.allOverridableAttributeNames_(typeMapping)) { + @Override + protected boolean accept(String o) { + if (mappedByRelationshipAttributes.isEmpty()) { + return true; + } + // overrideable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + String qualifier = + (o.indexOf('.') > 0) ? + o.substring(0, o.indexOf('.')) + : o; + return ! mappedByRelationshipAttributes.contains(qualifier); + } + }; + } + } + + + // **************** resource -> context *********************************** + + @Override + protected void initialize() { + super.initialize(); + this.mappedByRelationship = calculateMappedByRelationship(); + } + + + @Override + protected void update() { + super.update(); + setMappedByRelationship(calculateMappedByRelationship()); + } + + + // **************** validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + // [JPA 2.0] if the embedded id is mapped by a relationship, then any specified + // attribute overrides are in error + // (in JPA 1.0, this will obviously never be reached) + if (isMappedByRelationship() + && getAttributeOverrideContainer().specifiedAttributeOverridesSize() > 0) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.EMBEDDED_ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_ATTRIBUTE_OVERRIDES_SPECIFIED, + new String[] {}, + getAttributeOverrideContainer(), + getAttributeOverrideContainer().getValidationTextRange(astRoot))); + } + } +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java new file mode 100644 index 0000000000..3f4ca58cdb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java @@ -0,0 +1,375 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.RelationshipReference; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaBaseEmbeddedMapping; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.JpaFactory2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaEmbeddedMapping2_0; +import org.eclipse.jpt.core.resource.java.EmbeddedAnnotation; +import org.eclipse.jpt.core.resource.java.JPA; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.Transformer; +import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericJavaEmbeddedMapping + extends AbstractJavaBaseEmbeddedMapping<EmbeddedAnnotation> + implements JavaEmbeddedMapping2_0 +{ + protected final JavaAssociationOverrideContainer associationOverrideContainer; + + public GenericJavaEmbeddedMapping(JavaPersistentAttribute parent) { + super(parent); + this.associationOverrideContainer = this.buildAssociationOverrideContainer(); + } + + @Override + protected void initialize() { + super.initialize(); + this.associationOverrideContainer.initialize(this.getResourcePersistentAttribute()); + } + + @Override + protected void update() { + super.update(); + this.associationOverrideContainer.update(this.getResourcePersistentAttribute()); + } + + @Override + public void postUpdate() { + super.postUpdate(); + this.associationOverrideContainer.postUpdate(); + } + + //****************** JavaAttributeMapping implementation ******************* + + public String getKey() { + return MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY; + } + + public String getAnnotationName() { + return EmbeddedAnnotation.ANNOTATION_NAME; + } + + //only putting this in EmbeddedMapping since relationship mappings + //defined within an embedded id class are not supported by the 2.0 spec. + //i.e. the mappedBy choices will not include attributes nested in an embedded mapping + @Override + public Iterator<String> allMappingNames() { + return this.isJpa2_0Compatible() ? + new CompositeIterator<String>(this.getName(), this.allEmbeddableAttributeMappingNames()) : + super.allMappingNames(); + } + + protected Iterator<String> allEmbeddableAttributeMappingNames() { + return this.embeddableOverrideableMappingNames( + new Transformer<AttributeMapping, Iterator<String>>() { + public Iterator<String> transform(AttributeMapping mapping) { + return mapping.allMappingNames(); + } + } + ); + } + + @Override + public AttributeMapping resolveAttributeMapping(String name) { + AttributeMapping resolvedMapping = super.resolveAttributeMapping(name); + if (resolvedMapping != null) { + return resolvedMapping; + } + if (this.isJpa2_0Compatible()) { + int dotIndex = name.indexOf('.'); + if (dotIndex != -1) { + if (getName().equals(name.substring(0, dotIndex))) { + for (AttributeMapping attributeMapping : CollectionTools.iterable(embeddableAttributeMappings())) { + resolvedMapping = attributeMapping.resolveAttributeMapping(name.substring(dotIndex + 1)); + if (resolvedMapping != null) { + return resolvedMapping; + } + } + } + } + } + return null; + } + + @Override + public RelationshipReference resolveRelationshipReference(String attributeName) { + if (this.isJpa2_0Compatible()) { + int dotIndex = attributeName.indexOf('.'); + if (dotIndex != -1) { + if (getName().equals(attributeName.substring(0, dotIndex))) { + attributeName = attributeName.substring(dotIndex + 1); + AssociationOverride override = getAssociationOverrideContainer().getAssociationOverrideNamed(attributeName); + if (override != null && !override.isVirtual()) { + return override.getRelationshipReference(); + } + if (this.getTargetEmbeddable() == null) { + return null; + } + return this.getTargetEmbeddable().resolveRelationshipReference(attributeName); + } + } + } + return null; + } + + //****************** AbstractJavaAttributeMapping implementation ******************* + @Override + protected void addSupportingAnnotationNamesTo(Vector<String> names) { + super.addSupportingAnnotationNamesTo(names); + if (this.isJpa2_0Compatible()) { + names.add(JPA.ASSOCIATION_OVERRIDE); + names.add(JPA.ASSOCIATION_OVERRIDES); + } + } + + + //****************** association overrides - 2.0 supports this ******************* + + protected JavaAssociationOverrideContainer buildAssociationOverrideContainer() { + return this.isJpa2_0Compatible() ? + ((JpaFactory2_0) this.getJpaFactory()).buildJavaAssociationOverrideContainer(this, new AssociationOverrideContainerOwner()) : + new NullJavaAssociationOverrideContainer(this); + } + + public JavaAssociationOverrideContainer getAssociationOverrideContainer() { + return this.associationOverrideContainer; + } + + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + + result = getAssociationOverrideContainer().javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + return null; + } + + + // ********** validation ********** + + @Override + protected void validateOverrides(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validateOverrides(messages, reporter, astRoot); + this.getAssociationOverrideContainer().validate(messages, reporter, astRoot); + } + + + // ********** association override container owner ********** + + protected class AssociationOverrideContainerOwner + implements JavaAssociationOverrideContainer.Owner + { + public TypeMapping getTypeMapping() { + return GenericJavaEmbeddedMapping.this.getTypeMapping(); + } + + public TypeMapping getOverridableTypeMapping() { + return GenericJavaEmbeddedMapping.this.getOverridableTypeMapping(); + } + + public Iterator<String> allOverridableNames() { + TypeMapping typeMapping = getOverridableTypeMapping(); + return (typeMapping == null) ? + EmptyIterator.<String>instance() + : typeMapping.allOverridableAssociationNames(); + } + + public RelationshipReference resolveRelationshipReference(String associationOverrideName) { + return MappingTools.resolveRelationshipReference(getOverridableTypeMapping(), associationOverrideName); + } + + public boolean tableNameIsInvalid(String tableName) { + return getTypeMapping().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getTypeMapping().associatedTableNamesIncludingInherited(); + } + + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + return getTypeMapping().getDbTable(tableName); + } + + public String getDefaultTableName() { + return getTypeMapping().getPrimaryTableName(); + } + + public String getPossiblePrefix() { + return null; + } + + public String getWritePrefix() { + return null; + } + + //no prefix, so always true + public boolean isRelevant(String overrideName) { + return true; + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaEmbeddedMapping.this.getValidationTextRange(astRoot); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + if (override.isVirtual()) { + return this.buildVirtualOverrideColumnTableNotValidMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_TABLE_NOT_VALID, + new String[] { + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideColumnTableNotValidMessage(String overrideName, BaseColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID, + new String[] { + overrideName, + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, + column, + textRange + ); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + if (override.isVirtual()) { + return this.buildVirtualColumnUnresolvedNameMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualColumnUnresolvedNameMessage(String overrideName, NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {overrideName, column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildColumnUnresolvedReferencedColumnNameMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (override.isVirtual()) { + return this.buildVirtualColumnUnresolvedReferencedColumnNameMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualColumnUnresolvedReferencedColumnNameMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {overrideName, column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (override.isVirtual()) { + return this.buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {overrideName}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (override.isVirtual()) { + return this.buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {overrideName}, + column, + textRange + ); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEntity.java new file mode 100644 index 0000000000..fed7a6e563 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEntity.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaEntity; +import org.eclipse.jpt.core.internal.jpa2.context.java.NullJavaCacheable2_0; +import org.eclipse.jpt.core.jpa2.JpaFactory2_0; +import org.eclipse.jpt.core.jpa2.context.CacheableHolder2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaCacheable2_0; +import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; + +public class GenericJavaEntity + extends AbstractJavaEntity +{ + + protected final JavaCacheable2_0 cacheable; + + public GenericJavaEntity(JavaPersistentType parent) { + super(parent); + this.cacheable = this.buildCacheable(); + } + + @Override + public void initialize(JavaResourcePersistentType resourcePersistentType) { + super.initialize(resourcePersistentType); + this.cacheable.initialize(resourcePersistentType); + } + + @Override + public void update(JavaResourcePersistentType resourcePersistentType) { + super.update(resourcePersistentType); + this.cacheable.update(resourcePersistentType); + } + + //****************** Entity2_0 implementation ******************* + + protected JavaCacheable2_0 buildCacheable() { + return this.isJpa2_0Compatible() ? + ((JpaFactory2_0) this.getJpaFactory()).buildJavaCacheable(this) : + new NullJavaCacheable2_0(this); + } + + public JavaCacheable2_0 getCacheable() { + return this.cacheable; + } + + public boolean calculateDefaultCacheable() { + CacheableHolder2_0 parentEntity = (CacheableHolder2_0) getParentEntity(); + if (parentEntity != null) { + return parentEntity.getCacheable().isCacheable(); + } + return ((PersistenceUnit2_0) getPersistenceUnit()).calculateDefaultCacheable(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java new file mode 100644 index 0000000000..ee186c564a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.EnumType; +import org.eclipse.jpt.core.context.EnumeratedConverter; +import org.eclipse.jpt.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.core.context.java.JavaEnumeratedConverter; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.EnumeratedAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaEnumeratedConverter extends AbstractJavaJpaContextNode + implements JavaEnumeratedConverter +{ + protected EnumType specifiedEnumType; + + protected JavaResourcePersistentAttribute resourcePersistenceAttribute; + + public GenericJavaEnumeratedConverter(JavaAttributeMapping parent, JavaResourcePersistentAttribute jrpa) { + super(parent); + this.initialize(jrpa); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.ENUMERATED_CONVERTER; + } + + protected String getAnnotationName() { + return EnumeratedAnnotation.ANNOTATION_NAME; + } + + public void addToResourceModel() { + this.resourcePersistenceAttribute.addAnnotation(getAnnotationName()); + } + + public void removeFromResourceModel() { + this.resourcePersistenceAttribute.removeAnnotation(getAnnotationName()); + } + + public EnumType getEnumType() { + return getSpecifiedEnumType() == null ? getDefaultEnumType() : getSpecifiedEnumType(); + } + + public EnumType getDefaultEnumType() { + return EnumeratedConverter.DEFAULT_ENUM_TYPE; + } + + public EnumType getSpecifiedEnumType() { + return this.specifiedEnumType; + } + + public void setSpecifiedEnumType(EnumType newSpecifiedEnumType) { + EnumType oldSpecifiedEnumType = this.specifiedEnumType; + this.specifiedEnumType = newSpecifiedEnumType; + this.getResourceEnumerated().setValue(EnumType.toJavaResourceModel(newSpecifiedEnumType)); + firePropertyChanged(EnumeratedConverter.SPECIFIED_ENUM_TYPE_PROPERTY, oldSpecifiedEnumType, newSpecifiedEnumType); + } + + protected void setSpecifiedEnumType_(EnumType newSpecifiedEnumType) { + EnumType oldSpecifiedEnumType = this.specifiedEnumType; + this.specifiedEnumType = newSpecifiedEnumType; + firePropertyChanged(EnumeratedConverter.SPECIFIED_ENUM_TYPE_PROPERTY, oldSpecifiedEnumType, newSpecifiedEnumType); + } + + protected EnumeratedAnnotation getResourceEnumerated() { + return (EnumeratedAnnotation) this.resourcePersistenceAttribute. + getAnnotation(getAnnotationName()); + } + + protected void initialize(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistenceAttribute = jrpa; + this.specifiedEnumType = this.specifiedEnumType(getResourceEnumerated()); + } + + public void update(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistenceAttribute = jrpa; + this.setSpecifiedEnumType_(this.specifiedEnumType(getResourceEnumerated())); + } + + protected EnumType specifiedEnumType(EnumeratedAnnotation resourceEnumerated) { + return resourceEnumerated == null ? null : EnumType.fromJavaResourceModel(resourceEnumerated.getValue()); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.getResourceEnumerated().getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java new file mode 100644 index 0000000000..d5993917a1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.GeneratedValue; +import org.eclipse.jpt.core.context.GenerationType; +import org.eclipse.jpt.core.context.Generator; +import org.eclipse.jpt.core.context.java.JavaGeneratedValue; +import org.eclipse.jpt.core.context.java.JavaIdMapping; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.GeneratedValueAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * + */ +public class GenericJavaGeneratedValue + extends AbstractJavaJpaContextNode + implements JavaGeneratedValue +{ + protected GeneratedValueAnnotation resourceGeneratedValue; + + protected GenerationType specifiedStrategy; + + protected String specifiedGenerator; + + // always null? + protected String defaultGenerator = null; + + + public GenericJavaGeneratedValue(JavaIdMapping parent) { + super(parent); + } + + public void initialize(GeneratedValueAnnotation generatedValueAnnotation) { + this.resourceGeneratedValue = generatedValueAnnotation; + this.specifiedStrategy = this.buildSpecifiedStrategy(); + this.specifiedGenerator = generatedValueAnnotation.getGenerator(); + } + + + // ********** strategy ********** + + public GenerationType getStrategy() { + return (this.specifiedStrategy != null) ? this.specifiedStrategy : this.getDefaultStrategy(); + } + + public GenerationType getDefaultStrategy() { + return GeneratedValue.DEFAULT_STRATEGY; + } + + public GenerationType getSpecifiedStrategy() { + return this.specifiedStrategy; + } + + public void setSpecifiedStrategy(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.resourceGeneratedValue.setStrategy(GenerationType.toJavaResourceModel(strategy)); + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + protected void setSpecifiedStrategy_(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + + // ********** generator ********** + + public String getGenerator() { + return (this.specifiedGenerator != null) ? this.specifiedGenerator : this.defaultGenerator; + } + + public String getDefaultGenerator() { + return this.defaultGenerator; + } + + public String getSpecifiedGenerator() { + return this.specifiedGenerator; + } + + public void setSpecifiedGenerator(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.resourceGeneratedValue.setGenerator(generator); + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + protected void setSpecifiedGenerator_(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + + // ********** text ranges ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.resourceGeneratedValue.getTextRange(astRoot); + } + + public TextRange getGeneratorTextRange(CompilationUnit astRoot) { + return this.resourceGeneratedValue.getGeneratorTextRange(astRoot); + } + + + // ********** completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.generatorTouches(pos, astRoot)) { + return this.javaCandidateGeneratorNames(filter); + } + return null; + } + + protected boolean generatorTouches(int pos, CompilationUnit astRoot) { + return this.resourceGeneratedValue.generatorTouches(pos, astRoot); + } + + protected Iterator<String> javaCandidateGeneratorNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.candidateGeneratorNames(filter)); + } + + protected Iterator<String> candidateGeneratorNames(Filter<String> filter) { + return new FilteringIterator<String>(this.candidateGeneratorNames(), filter); + } + + protected Iterator<String> candidateGeneratorNames() { + return new TransformationIterator<Generator, String>(this.candidateGenerators()) { + @Override + protected String transform(Generator generator) { + return generator.getName(); + } + }; + } + + protected Iterator<Generator> candidateGenerators() { + return this.getPersistenceUnit().generators(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + String generator = this.getGenerator(); + if (generator == null) { + return; + } + + for (Iterator<Generator> stream = this.getPersistenceUnit().generators(); stream.hasNext(); ) { + if (generator.equals(stream.next().getName())) { + return; + } + } + + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME, + new String[] {generator}, + this.getParent(), + this.getGeneratorTextRange(astRoot) + ) + ); + } + + + // ********** update from resource model ********** + + public void update(GeneratedValueAnnotation generatedValueAnnotation) { + this.resourceGeneratedValue = generatedValueAnnotation; + this.setSpecifiedStrategy_(this.buildSpecifiedStrategy()); + this.setSpecifiedGenerator_(generatedValueAnnotation.getGenerator()); + } + + protected GenerationType buildSpecifiedStrategy() { + return GenerationType.fromJavaResourceModel(this.resourceGeneratedValue.getStrategy()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java new file mode 100644 index 0000000000..1f4586a705 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java @@ -0,0 +1,270 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Generator; +import org.eclipse.jpt.core.context.java.JavaGenerator; +import org.eclipse.jpt.core.context.java.JavaGeneratorContainer; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaSequenceGenerator; +import org.eclipse.jpt.core.context.java.JavaTableGenerator; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.resource.java.SequenceGeneratorAnnotation; +import org.eclipse.jpt.core.resource.java.TableGeneratorAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaGeneratorContainer extends AbstractJavaJpaContextNode + implements JavaGeneratorContainer +{ + protected JavaResourcePersistentMember javaResourcePersistentMember; + + protected JavaSequenceGenerator sequenceGenerator; + + protected JavaTableGenerator tableGenerator; + + public GenericJavaGeneratorContainer(JavaJpaContextNode parent) { + super(parent); + } + + @Override + public JavaJpaContextNode getParent() { + return (JavaJpaContextNode) super.getParent(); + } + + public JavaTableGenerator addTableGenerator() { + if (getTableGenerator() != null) { + throw new IllegalStateException("tableGenerator already exists"); //$NON-NLS-1$ + } + this.tableGenerator = getJpaFactory().buildJavaTableGenerator(this); + TableGeneratorAnnotation tableGeneratorResource = + (TableGeneratorAnnotation) this.javaResourcePersistentMember. + addAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + this.tableGenerator.initialize(tableGeneratorResource); + firePropertyChanged(TABLE_GENERATOR_PROPERTY, null, this.tableGenerator); + return this.tableGenerator; + } + + public void removeTableGenerator() { + if (getTableGenerator() == null) { + throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); //$NON-NLS-1$ + } + JavaTableGenerator oldTableGenerator = this.tableGenerator; + this.tableGenerator = null; + this.javaResourcePersistentMember.removeAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + firePropertyChanged(TABLE_GENERATOR_PROPERTY, oldTableGenerator, null); + } + + public JavaTableGenerator getTableGenerator() { + return this.tableGenerator; + } + + protected void setTableGenerator(JavaTableGenerator newTableGenerator) { + JavaTableGenerator oldTableGenerator = this.tableGenerator; + this.tableGenerator = newTableGenerator; + firePropertyChanged(TABLE_GENERATOR_PROPERTY, oldTableGenerator, newTableGenerator); + } + + public JavaSequenceGenerator addSequenceGenerator() { + if (getSequenceGenerator() != null) { + throw new IllegalStateException("sequenceGenerator already exists"); //$NON-NLS-1$ + } + this.sequenceGenerator = getJpaFactory().buildJavaSequenceGenerator(this); + SequenceGeneratorAnnotation sequenceGeneratorResource = + (SequenceGeneratorAnnotation) this.javaResourcePersistentMember. + addAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + this.sequenceGenerator.initialize(sequenceGeneratorResource); + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, null, this.sequenceGenerator); + return this.sequenceGenerator; + } + + public void removeSequenceGenerator() { + if (getSequenceGenerator() == null) { + throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); //$NON-NLS-1$ + } + JavaSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; + this.sequenceGenerator = null; + this.javaResourcePersistentMember.removeAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, oldSequenceGenerator,null); + } + + public JavaSequenceGenerator getSequenceGenerator() { + return this.sequenceGenerator; + } + + protected void setSequenceGenerator(JavaSequenceGenerator newSequenceGenerator) { + JavaSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; + this.sequenceGenerator = newSequenceGenerator; + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, oldSequenceGenerator, newSequenceGenerator); + } + + + public void initialize(JavaResourcePersistentMember jrpm) { + this.javaResourcePersistentMember = jrpm; + this.initializeTableGenerator(); + this.initializeSequenceGenerator(); + } + + protected void initializeTableGenerator() { + TableGeneratorAnnotation tableGeneratorResource = getResourceTableGenerator(); + if (tableGeneratorResource != null) { + this.tableGenerator = buildTableGenerator(tableGeneratorResource); + } + } + + protected void initializeSequenceGenerator() { + SequenceGeneratorAnnotation sequenceGeneratorResource = getResourceSequenceGenerator(); + if (sequenceGeneratorResource != null) { + this.sequenceGenerator = buildSequenceGenerator(sequenceGeneratorResource); + } + } + + public void update(JavaResourcePersistentMember jrpm) { + this.javaResourcePersistentMember = jrpm; + this.updateTableGenerator(); + this.updateSequenceGenerator(); + } + + protected void updateTableGenerator() { + TableGeneratorAnnotation tableGeneratorResource = getResourceTableGenerator(); + if (tableGeneratorResource == null) { + if (getTableGenerator() != null) { + setTableGenerator(null); + } + } + else { + if (getTableGenerator() == null) { + setTableGenerator(buildTableGenerator(tableGeneratorResource)); + } + else { + getTableGenerator().update(tableGeneratorResource); + } + } + } + + protected JavaTableGenerator buildTableGenerator(TableGeneratorAnnotation tableGeneratorResource) { + JavaTableGenerator generator = getJpaFactory().buildJavaTableGenerator(this); + generator.initialize(tableGeneratorResource); + return generator; + } + + protected TableGeneratorAnnotation getResourceTableGenerator() { + return (TableGeneratorAnnotation) this.javaResourcePersistentMember. + getAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + } + + protected void updateSequenceGenerator() { + SequenceGeneratorAnnotation sequenceGeneratorResource = getResourceSequenceGenerator(); + if (sequenceGeneratorResource == null) { + if (getSequenceGenerator() != null) { + setSequenceGenerator(null); + } + } + else { + if (getSequenceGenerator() == null) { + setSequenceGenerator(buildSequenceGenerator(sequenceGeneratorResource)); + } + else { + getSequenceGenerator().update(sequenceGeneratorResource); + } + } + } + + protected JavaSequenceGenerator buildSequenceGenerator(SequenceGeneratorAnnotation sequenceGeneratorResource) { + JavaSequenceGenerator generator = getJpaFactory().buildJavaSequenceGenerator(this); + generator.initialize(sequenceGeneratorResource); + return generator; + } + + protected SequenceGeneratorAnnotation getResourceSequenceGenerator() { + return (SequenceGeneratorAnnotation) this.javaResourcePersistentMember. + getAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + } + + + //******************** Code Completion ************************* + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.getTableGenerator() != null) { + result = this.getTableGenerator().javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + if (this.getSequenceGenerator() != null) { + result = this.getSequenceGenerator().javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + //********** Validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.validateGenerators(messages, astRoot); + } + + protected void validateGenerators(List<IMessage> messages, CompilationUnit astRoot) { + for (Iterator<JavaGenerator> localGenerators = this.generators(); localGenerators.hasNext(); ) { + JavaGenerator localGenerator = localGenerators.next(); + for (Iterator<Generator> globalGenerators = this.getPersistenceUnit().generators(); globalGenerators.hasNext(); ) { + if (localGenerator.duplicates(globalGenerators.next())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_DUPLICATE_NAME, + new String[] {localGenerator.getName()}, + localGenerator, + localGenerator.getNameTextRange(astRoot) + ) + ); + } + } + } + } + + protected final Iterator<JavaGenerator> generators() { + ArrayList<JavaGenerator> generators = new ArrayList<JavaGenerator>(); + this.addGeneratorsTo(generators); + return generators.iterator(); + } + + protected void addGeneratorsTo(ArrayList<JavaGenerator> generators) { + if (this.sequenceGenerator != null) { + generators.add(this.sequenceGenerator); + } + if (this.tableGenerator != null) { + generators.add(this.tableGenerator); + } + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.javaResourcePersistentMember.getTextRange(astRoot); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaIdMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaIdMapping.java new file mode 100644 index 0000000000..97620c7e05 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaIdMapping.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaIdMapping; + + +public class GenericJavaIdMapping + extends AbstractJavaIdMapping +{ + + public GenericJavaIdMapping(JavaPersistentAttribute parent) { + super(parent); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinColumn.java new file mode 100644 index 0000000000..a357dd5e90 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinColumn.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaBaseColumn; +import org.eclipse.jpt.core.resource.java.JoinColumnAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + + +public class GenericJavaJoinColumn extends AbstractJavaBaseColumn<JoinColumnAnnotation> implements JavaJoinColumn +{ + + protected String specifiedReferencedColumnName; + + protected String defaultReferencedColumnName; + + public GenericJavaJoinColumn(JavaJpaContextNode parent, JavaJoinColumn.Owner owner) { + super(parent, owner); + } + + @Override + public void initialize(JoinColumnAnnotation annotation) { + super.initialize(annotation); + this.specifiedReferencedColumnName = annotation.getReferencedColumnName(); + this.defaultReferencedColumnName = this.buildDefaultReferencedColumnName(); + } + + @Override + public void update(JoinColumnAnnotation annotation) { + super.update(annotation); + this.setSpecifiedReferencedColumnName_(annotation.getReferencedColumnName()); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName == null) ? this.defaultReferencedColumnName : this.specifiedReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + this.getResourceColumn().setReferencedColumnName(newSpecifiedReferencedColumnName); + firePropertyChanged(BaseJoinColumn.SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + protected void setSpecifiedReferencedColumnName_(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + firePropertyChanged(BaseJoinColumn.SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String newDefaultReferencedColumnName) { + String oldDefaultReferencedColumnName = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = newDefaultReferencedColumnName; + firePropertyChanged(BaseJoinColumn.DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, oldDefaultReferencedColumnName, newDefaultReferencedColumnName); + } + + + @Override + public JavaJoinColumn.Owner getOwner() { + return (JavaJoinColumn.Owner) super.getOwner(); + } + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + public Table getReferencedColumnDbTable() { + return getOwner().getReferencedColumnDbTable(); + } + + public Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public boolean referencedColumnNameTouches(int pos, CompilationUnit astRoot) { + return getResourceColumn().referencedColumnNameTouches(pos, astRoot); + } + + @Override + public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.referencedColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateReferencedColumnNames(filter).iterator(); + } + return null; + } + + private Iterable<String> getJavaCandidateReferencedColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateReferencedColumnNames(filter)); + } + + private Iterable<String> getCandidateReferencedColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateReferencedColumnNames(), filter); + } + + private Iterable<String> getCandidateReferencedColumnNames() { + Table table = this.getOwner().getReferencedColumnDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + public boolean isReferencedColumnResolved() { + return getReferencedDbColumn() != null; + } + + public TextRange getReferencedColumnNameTextRange(CompilationUnit astRoot) { + TextRange textRange = getResourceColumn().getReferencedColumnNameTextRange(astRoot); + return (textRange != null) ? textRange : getOwner().getValidationTextRange(astRoot); + } + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.getOwner()); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.getOwner()); + } + + @Override + //this method will only be called if the table validates correctly + protected void validateName(List<IMessage> messages, CompilationUnit astRoot) { + this.validateJoinColumnName(messages, astRoot); + this.validateReferencedColumnName(messages, astRoot); + } + + protected void validateJoinColumnName(List<IMessage> messages, CompilationUnit astRoot) { + if (getSpecifiedName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedNameMultipleJoinColumnsMessage(astRoot)); + } + else if (this.getName() != null){ + super.validateName(messages, astRoot); + } + //If the name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected void validateReferencedColumnName(List<IMessage> messages, CompilationUnit astRoot) { + if (getSpecifiedReferencedColumnName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(astRoot)); + } + else if (this.getSpecifiedReferencedColumnName() != null) { + if (this.getReferencedColumnDbTable() != null && ! this.isReferencedColumnResolved()) { + messages.add(getOwner().buildUnresolvedReferencedColumnNameMessage(this, this.getReferencedColumnNameTextRange(astRoot))); + } + } + //If the referenced column name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(CompilationUnit astRoot) { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(this, getNameTextRange(astRoot)); + } + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(CompilationUnit astRoot) { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(this, getReferencedColumnNameTextRange(astRoot)); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java new file mode 100644 index 0000000000..d9c2c680b8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaJoinTable.java @@ -0,0 +1,594 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.PersistentAttribute; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJoinTable; +import org.eclipse.jpt.core.context.java.JavaJoinTableJoiningStrategy; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.resource.java.NullJoinColumnAnnotation; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JoinColumnAnnotation; +import org.eclipse.jpt.core.resource.java.JoinTableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java join table + */ +public class GenericJavaJoinTable + extends GenericJavaReferenceTable + implements JavaJoinTable +{ + + protected JavaJoinColumn defaultInverseJoinColumn; + + protected final Vector<JavaJoinColumn> specifiedInverseJoinColumns = new Vector<JavaJoinColumn>(); + protected final JavaJoinColumn.Owner inverseJoinColumnOwner; + + + public GenericJavaJoinTable(JavaJoinTableJoiningStrategy parent) { + super(parent); + this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner(); + } + + @Override + protected JavaJoinColumn.Owner buildJoinColumnOwner() { + return new JoinColumnOwner(); + } + + protected JavaJoinColumn.Owner buildInverseJoinColumnOwner() { + return new InverseJoinColumnOwner(); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getParent().getRelationshipReference().getRelationshipMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return getRelationshipMapping().getPersistentAttribute(); + } + + public void initialize(JoinTableAnnotation joinTable) { + super.initialize(joinTable); + this.initializeSpecifiedInverseJoinColumns(joinTable); + this.initializeDefaultInverseJoinColumn(joinTable); + } + + public void update(JoinTableAnnotation joinTable) { + super.update(joinTable); + this.updateSpecifiedInverseJoinColumns(joinTable); + this.updateDefaultInverseJoinColumn(joinTable); + } + + + // ********** AbstractJavaTable implementation ********** + + @Override + public JavaJoinTableJoiningStrategy getParent() { + return (JavaJoinTableJoiningStrategy) super.getParent(); + } + + @Override + protected String getAnnotationName() { + return JoinTableAnnotation.ANNOTATION_NAME; + } + + @Override + protected String buildDefaultName() { + return this.getParent().getJoinTableDefaultName(); + } + + @Override + protected JoinTableAnnotation getAnnotation() { + return this.getParent().getAnnotation(); + } + + + // ********** inverse join columns ********** + + public ListIterator<JavaJoinColumn> inverseJoinColumns() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumns() : this.defaultInverseJoinColumns(); + } + + public int inverseJoinColumnsSize() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumnsSize() : this.defaultInverseJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedInverseJoinColumn() { + MappingTools.convertJoinTableDefaultToSpecifiedInverseJoinColumn(this); + } + + protected JavaJoinColumn buildInverseJoinColumn(JoinColumnAnnotation joinColumnAnnotation) { + return this.buildJoinColumn(joinColumnAnnotation, this.inverseJoinColumnOwner); + } + + + // ********** default inverse join column ********** + + public JavaJoinColumn getDefaultInverseJoinColumn() { + return this.defaultInverseJoinColumn; + } + + protected void setDefaultInverseJoinColumn(JavaJoinColumn defaultInverseJoinColumn) { + JavaJoinColumn old = this.defaultInverseJoinColumn; + this.defaultInverseJoinColumn = defaultInverseJoinColumn; + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, old, defaultInverseJoinColumn); + } + + protected ListIterator<JavaJoinColumn> defaultInverseJoinColumns() { + if (this.defaultInverseJoinColumn != null) { + return new SingleElementListIterator<JavaJoinColumn>(this.defaultInverseJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultInverseJoinColumnsSize() { + return (this.defaultInverseJoinColumn == null) ? 0 : 1; + } + + protected void initializeDefaultInverseJoinColumn(JoinTableAnnotation joinTableAnnotation) { + if (this.shouldBuildDefaultInverseJoinColumn()) { + this.defaultInverseJoinColumn = this.buildInverseJoinColumn(new NullJoinColumnAnnotation(joinTableAnnotation)); + } + } + + protected boolean shouldBuildDefaultInverseJoinColumn() { + return ! this.hasSpecifiedInverseJoinColumns(); + } + + protected void updateDefaultInverseJoinColumn(JoinTableAnnotation joinTableAnnotation) { + if (this.shouldBuildDefaultInverseJoinColumn()) { + if (this.defaultInverseJoinColumn == null) { + this.setDefaultInverseJoinColumn(this.buildInverseJoinColumn(new NullJoinColumnAnnotation(joinTableAnnotation))); + } else { + this.defaultInverseJoinColumn.update(new NullJoinColumnAnnotation(joinTableAnnotation)); + } + } else { + this.setDefaultInverseJoinColumn(null); + } + } + + + // ********** specified inverse join columns ********** + + public ListIterator<JavaJoinColumn> specifiedInverseJoinColumns() { + return new CloneListIterator<JavaJoinColumn>(this.specifiedInverseJoinColumns); + } + + public int specifiedInverseJoinColumnsSize() { + return this.specifiedInverseJoinColumns.size(); + } + + public boolean hasSpecifiedInverseJoinColumns() { + return this.specifiedInverseJoinColumns.size() != 0; + } + + public JavaJoinColumn addSpecifiedInverseJoinColumn(int index) { + // Clear out the default now so it doesn't get removed during an update and + // cause change notifications to be sent to the UI in the wrong order. + // If the default is already null, nothing will happen. + JoinColumn oldDefault = this.defaultInverseJoinColumn; + this.defaultInverseJoinColumn = null; + + JavaJoinColumn inverseJoinColumn = this.getJpaFactory().buildJavaJoinColumn(this, this.inverseJoinColumnOwner); + this.specifiedInverseJoinColumns.add(index, inverseJoinColumn); + JoinTableAnnotation joinTableAnnotation = this.getAnnotation(); + JoinColumnAnnotation joinColumnAnnotation = joinTableAnnotation.addInverseJoinColumn(index); + inverseJoinColumn.initialize(joinColumnAnnotation); + this.fireItemAdded(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, index, inverseJoinColumn); + + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, oldDefault, null); + return inverseJoinColumn; + } + + protected void addSpecifiedInverseJoinColumn(int index, JavaJoinColumn inverseJoinColumn) { + this.addItemToList(index, inverseJoinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedInverseJoinColumn(JavaJoinColumn inverseJoinColumn) { + this.addSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.size(), inverseJoinColumn); + } + + public void removeSpecifiedInverseJoinColumn(JoinColumn inverseJoinColumn) { + this.removeSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.indexOf(inverseJoinColumn)); + } + + public void removeSpecifiedInverseJoinColumn(int index) { + JavaJoinColumn removedJoinColumn = this.specifiedInverseJoinColumns.remove(index); + if ( ! this.hasSpecifiedInverseJoinColumns()) { + //create the defaultJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultInverseJoinColumn = this.buildInverseJoinColumn(new NullJoinColumnAnnotation(this.getAnnotation())); + } + this.getAnnotation().removeInverseJoinColumn(index); + this.fireItemRemoved(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, index, removedJoinColumn); + if (this.defaultInverseJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, null, this.defaultInverseJoinColumn); + } + } + + protected void removeSpecifiedInverseJoinColumn_(JavaJoinColumn joinColumn) { + this.removeItemFromList(joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedInverseJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedInverseJoinColumns, targetIndex, sourceIndex); + this.getAnnotation().moveInverseJoinColumn(targetIndex, sourceIndex); + this.fireItemMoved(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + public void clearSpecifiedInverseJoinColumns() { + // for now, we have to remove annotations one at a time... + for (int i = this.specifiedInverseJoinColumns.size(); i-- > 0; ) { + this.removeSpecifiedInverseJoinColumn(i); + } + } + + protected void initializeSpecifiedInverseJoinColumns(JoinTableAnnotation joinTableAnnotation) { + for (ListIterator<JoinColumnAnnotation> stream = joinTableAnnotation.inverseJoinColumns(); stream.hasNext(); ) { + this.specifiedInverseJoinColumns.add(this.buildInverseJoinColumn(stream.next())); + } + } + + protected void updateSpecifiedInverseJoinColumns(JoinTableAnnotation joinTableAnnotation) { + ListIterator<JavaJoinColumn> joinColumns = this.specifiedInverseJoinColumns(); + ListIterator<JoinColumnAnnotation> joinColumnAnnotations = joinTableAnnotation.inverseJoinColumns(); + + while (joinColumns.hasNext()) { + JavaJoinColumn joinColumn = joinColumns.next(); + if (joinColumnAnnotations.hasNext()) { + joinColumn.update(joinColumnAnnotations.next()); + } else { + this.removeSpecifiedInverseJoinColumn_(joinColumn); + } + } + + while (joinColumnAnnotations.hasNext()) { + this.addSpecifiedInverseJoinColumn(this.buildInverseJoinColumn(joinColumnAnnotations.next())); + } + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaJoinColumn column : CollectionTools.iterable(this.inverseJoinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + + // ********** validation ********** + + @Override + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validateJoinColumns(messages, reporter, astRoot); + this.validateJoinColumns(this.inverseJoinColumns(), messages, reporter, astRoot); + } + + @Override + protected boolean shouldValidateAgainstDatabase() { + return getParent().shouldValidateAgainstDatabase(); + } + + @Override + protected String getUnresolvedCatalogMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getUnresolvedSchemaMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getUnresolvedNameMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME; + } + + + // ********** join column owner adapters ********** + + /** + * just a little common behavior + */ + protected abstract class AbstractJoinColumnOwner + implements JavaJoinColumn.Owner + { + protected AbstractJoinColumnOwner() { + super(); + } + + public TypeMapping getTypeMapping() { + return GenericJavaJoinTable.this.getParent().getRelationshipReference().getTypeMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return GenericJavaJoinTable.this.getPersistentAttribute(); + } + + /** + * If there is a specified table name it needs to be the same + * the default table name. the table is always the join table + */ + public boolean tableNameIsInvalid(String tableName) { + return !StringTools.stringsAreEqual(getDefaultTableName(), tableName); + } + + /** + * the join column can only be on the join table itself + */ + public Iterator<String> candidateTableNames() { + return EmptyIterator.instance(); + } + + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + if (GenericJavaJoinTable.this.getName() == null) { + return null; + } + return (GenericJavaJoinTable.this.getName().equals(tableName)) ? GenericJavaJoinTable.this.getDbTable() : null; + } + + /** + * by default, the join column is, obviously, in the join table; + * not sure whether it can be anywhere else... + */ + public String getDefaultTableName() { + return GenericJavaJoinTable.this.getName(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaJoinTable.this.getValidationTextRange(astRoot); + } + + public IMessage buildTableNotValidMessage(BaseColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getTableNotValidMessage(), + new String[] { + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.DOES_NOT_MATCH_JOIN_TABLE}, + column, + textRange + ); + } + + protected abstract String getTableNotValidMessage(); + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedNameMessage(), + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected abstract String getUnresolvedNameMessage(); + + public IMessage buildUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedReferencedColumnNameMessage(), + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected abstract String getUnresolvedReferencedColumnNameMessage(); + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnspecifiedNameMultipleJoinColumnsMessage(), + new String[0], + column, + textRange + ); + } + + protected abstract String getUnspecifiedNameMultipleJoinColumnsMessage(); + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[0], + column, + textRange + ); + } + protected abstract String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + + /** + * owner for "back-pointer" JoinColumns; + * these point at the source/owning entity + */ + protected class JoinColumnOwner + extends AbstractJoinColumnOwner + { + protected JoinColumnOwner() { + super(); + } + + public Entity getRelationshipTarget() { + return GenericJavaJoinTable.this.getParent().getRelationshipReference().getEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericJavaJoinTable.this.getRelationshipMapping(); + if (relationshipMapping == null) { + return null; + } + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity == null) { + return null; + } + for (PersistentAttribute each : + CollectionTools.iterable( + targetEntity.getPersistentType().allAttributes())) { + if (each.getMapping().isOwnedBy(relationshipMapping)) { + return each.getName(); + } + } + return null; + } + + public org.eclipse.jpt.db.Table getReferencedColumnDbTable() { + return getTypeMapping().getPrimaryDbTable(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericJavaJoinTable.this.defaultJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + //built in MappingTools.buildJoinColumnDefaultName() + return null; + } + + public int joinColumnsSize() { + return GenericJavaJoinTable.this.joinColumnsSize(); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getTableNotValidMessage() { + return JpaValidationMessages.JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + } + + + /** + * owner for "forward-pointer" JoinColumns; + * these point at the target/inverse entity + */ + protected class InverseJoinColumnOwner + extends AbstractJoinColumnOwner + { + protected InverseJoinColumnOwner() { + super(); + } + + public Entity getRelationshipTarget() { + RelationshipMapping relationshipMapping = GenericJavaJoinTable.this.getRelationshipMapping(); + return relationshipMapping == null ? null : relationshipMapping.getResolvedTargetEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericJavaJoinTable.this.getRelationshipMapping(); + return relationshipMapping == null ? null : relationshipMapping.getName(); + } + + public org.eclipse.jpt.db.Table getReferencedColumnDbTable() { + Entity relationshipTarget = getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.getPrimaryDbTable(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericJavaJoinTable.this.defaultInverseJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + //built in MappingTools.buildJoinColumnDefaultName() + return null; + } + + public int joinColumnsSize() { + return GenericJavaJoinTable.this.inverseJoinColumnsSize(); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getTableNotValidMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaLobConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaLobConverter.java new file mode 100644 index 0000000000..3755a7cd84 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaLobConverter.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.core.context.java.JavaLobConverter; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.resource.java.LobAnnotation; +import org.eclipse.jpt.core.resource.java.TemporalAnnotation; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaLobConverter extends AbstractJavaJpaContextNode + implements JavaLobConverter +{ + protected JavaResourcePersistentAttribute resourcePersistentAttribute; + + + public GenericJavaLobConverter(JavaAttributeMapping parent, JavaResourcePersistentAttribute jrpa) { + super(parent); + this.initialize(jrpa); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.LOB_CONVERTER; + } + + protected String getAnnotationName() { + return LobAnnotation.ANNOTATION_NAME; + } + + public void addToResourceModel() { + this.resourcePersistentAttribute.addAnnotation(getAnnotationName()); + } + + public void removeFromResourceModel() { + this.resourcePersistentAttribute.removeAnnotation(getAnnotationName()); + } + + protected TemporalAnnotation getResourceLob() { + return (TemporalAnnotation) this.resourcePersistentAttribute. + getAnnotation(getAnnotationName()); + } + + protected void initialize(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistentAttribute = jrpa; + } + + public void update(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistentAttribute = jrpa; + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return getResourceLob().getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java new file mode 100644 index 0000000000..4d0780cc47 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaManyToManyMapping; + + +public class GenericJavaManyToManyMapping + extends AbstractJavaManyToManyMapping +{ + public GenericJavaManyToManyMapping(JavaPersistentAttribute parent) { + super(parent); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java new file mode 100644 index 0000000000..d4730b8b38 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaManyToOneMapping; +import org.eclipse.jpt.core.internal.context.java.GenericJavaManyToOneRelationshipReference; +import org.eclipse.jpt.core.jpa2.context.java.JavaManyToOneRelationshipReference2_0; + + +public class GenericJavaManyToOneMapping + extends AbstractJavaManyToOneMapping +{ + public GenericJavaManyToOneMapping(JavaPersistentAttribute parent) { + super(parent); + } + + @Override + protected JavaManyToOneRelationshipReference2_0 buildRelationshipReference() { + return new GenericJavaManyToOneRelationshipReference(this); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java new file mode 100644 index 0000000000..3b19e3a6e7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaMappedSuperclass; + +public class GenericJavaMappedSuperclass extends AbstractJavaMappedSuperclass +{ + + public GenericJavaMappedSuperclass(JavaPersistentType parent) { + super(parent); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java new file mode 100644 index 0000000000..ab5d1a5d28 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.NamedNativeQuery; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaNamedNativeQuery; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaQuery; +import org.eclipse.jpt.core.resource.java.NamedNativeQueryAnnotation; + + +public class GenericJavaNamedNativeQuery extends AbstractJavaQuery + implements JavaNamedNativeQuery +{ + + protected String resultClass; + + protected String resultSetMapping; + + public GenericJavaNamedNativeQuery(JavaJpaContextNode parent) { + super(parent); + } + + @Override + protected NamedNativeQueryAnnotation getResourceQuery() { + return (NamedNativeQueryAnnotation) super.getResourceQuery(); + } + + public char getResultClassEnclosingTypeSeparator() { + return '.'; + } + + public String getResultClass() { + return this.resultClass; + } + + public void setResultClass(String newResultClass) { + String oldResultClass = this.resultClass; + this.resultClass = newResultClass; + getResourceQuery().setResultClass(newResultClass); + firePropertyChanged(NamedNativeQuery.RESULT_CLASS_PROPERTY, oldResultClass, newResultClass); + } + + protected void setResultClass_(String newResultClass) { + String oldResultClass = this.resultClass; + this.resultClass = newResultClass; + firePropertyChanged(NamedNativeQuery.RESULT_CLASS_PROPERTY, oldResultClass, newResultClass); + } + + public String getResultSetMapping() { + return this.resultSetMapping; + } + + public void setResultSetMapping(String newResultSetMapping) { + String oldResultSetMapping = this.resultSetMapping; + this.resultSetMapping = newResultSetMapping; + getResourceQuery().setResultSetMapping(newResultSetMapping); + firePropertyChanged(NamedNativeQuery.RESULT_SET_MAPPING_PROPERTY, oldResultSetMapping, newResultSetMapping); + } + + protected void setResultSetMapping_(String newResultSetMapping) { + String oldResultSetMapping = this.resultSetMapping; + this.resultSetMapping = newResultSetMapping; + firePropertyChanged(NamedNativeQuery.RESULT_SET_MAPPING_PROPERTY, oldResultSetMapping, newResultSetMapping); + } + + public void initialize(NamedNativeQueryAnnotation resourceQuery) { + super.initialize(resourceQuery); + this.resultClass = resourceQuery.getResultClass(); + this.resultSetMapping = resourceQuery.getResultSetMapping(); + } + + public void update(NamedNativeQueryAnnotation resourceQuery) { + super.update(resourceQuery); + this.setResultClass_(resourceQuery.getResultClass()); + this.setResultSetMapping_(resourceQuery.getResultSetMapping()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedQuery.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedQuery.java new file mode 100644 index 0000000000..d5d7a9630d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNamedQuery.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaNamedQuery; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaQuery; +import org.eclipse.jpt.core.resource.java.NamedQueryAnnotation; + + + +public class GenericJavaNamedQuery extends AbstractJavaQuery implements JavaNamedQuery +{ + + public GenericJavaNamedQuery(JavaJpaContextNode parent) { + super(parent); + } + + @Override + protected NamedQueryAnnotation getResourceQuery() { + return (NamedQueryAnnotation) super.getResourceQuery(); + } + + public void initialize(NamedQueryAnnotation resourceQuery) { + super.initialize(resourceQuery); + } + + public void update(NamedQueryAnnotation resourceQuery) { + super.update(resourceQuery); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java new file mode 100644 index 0000000000..790b932832 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaAttributeMapping; +import org.eclipse.jpt.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.core.resource.java.Annotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericJavaNullAttributeMapping + extends AbstractJavaAttributeMapping<Annotation> +{ + public GenericJavaNullAttributeMapping(JavaPersistentAttribute parent) { + super(parent); + } + + public String getKey() { + return MappingKeys.NULL_ATTRIBUTE_MAPPING_KEY; + } + + public String getAnnotationName() { + return null; + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + } + + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullConverter.java new file mode 100644 index 0000000000..7215197f00 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaNullConverter.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.core.context.java.JavaConverter; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaNullConverter extends AbstractJavaJpaContextNode + implements JavaConverter +{ + + public GenericJavaNullConverter(JavaAttributeMapping parent) { + super(parent); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.NO_CONVERTER; + } + + public void addToResourceModel() { + //do nothing + } + + public void removeFromResourceModel() { + //do nothin + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } + + public void update(JavaResourcePersistentAttribute jrpa) { + //do nothing + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java new file mode 100644 index 0000000000..68e49c9904 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.context.java.JavaRelationshipReference; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaOneToManyMapping; +import org.eclipse.jpt.core.jpa2.resource.java.OneToMany2_0Annotation; + + +public class GenericJavaOneToManyMapping + extends AbstractJavaOneToManyMapping<OneToMany2_0Annotation> +{ + + public GenericJavaOneToManyMapping(JavaPersistentAttribute parent) { + super(parent); + } + + @Override + protected JavaRelationshipReference buildRelationshipReference() { + return new GenericJavaOneToManyRelationshipReference(this); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyRelationshipReference.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyRelationshipReference.java new file mode 100644 index 0000000000..d54772a5c6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToManyRelationshipReference.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.JoiningStrategy; +import org.eclipse.jpt.core.context.java.JavaJoinColumnJoiningStrategy; +import org.eclipse.jpt.core.context.java.JavaOneToManyMapping; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaOneToManyRelationshipReference; + +public class GenericJavaOneToManyRelationshipReference + extends AbstractJavaOneToManyRelationshipReference +{ + + public GenericJavaOneToManyRelationshipReference(JavaOneToManyMapping parent) { + super(parent); + } + + @Override + protected JavaJoinColumnJoiningStrategy buildJoinColumnJoiningStrategy() { + return new NullJavaJoinColumnJoiningStrategy(this); + } + + // **************** join columns ******************************************* + + @Override + public boolean usesJoinColumnJoiningStrategy() { + return false; + } + + @Override + public void setJoinColumnJoiningStrategy() { + throw new UnsupportedOperationException("join column joining strategy not supported on a 1.0 1-m mapping"); //$NON-NLS-1$ + } + + @Override + public void unsetJoinColumnJoiningStrategy() { + throw new UnsupportedOperationException("join column joining strategy not supported on a 1.0 1-m mapping"); //$NON-NLS-1$ + } + + @Override + protected JoiningStrategy calculatePredominantJoiningStrategy() { + if (this.mappedByJoiningStrategy.getMappedByAttribute() != null) { + return this.mappedByJoiningStrategy; + } + return this.joinTableJoiningStrategy; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java new file mode 100644 index 0000000000..3c9b2f74c8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaOneToOneMapping; +import org.eclipse.jpt.core.internal.context.java.GenericJavaOneToOneRelationshipReference; +import org.eclipse.jpt.core.jpa2.context.java.JavaOneToOneRelationshipReference2_0; + + +public class GenericJavaOneToOneMapping + extends AbstractJavaOneToOneMapping +{ + public GenericJavaOneToOneMapping(JavaPersistentAttribute parent) { + super(parent); + } + + @Override + protected JavaOneToOneRelationshipReference2_0 buildRelationshipReference() { + return new GenericJavaOneToOneRelationshipReference(this); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOrderable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOrderable.java new file mode 100644 index 0000000000..6ebe7b84fc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaOrderable.java @@ -0,0 +1,401 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.Orderable; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.core.context.java.JavaNamedColumn; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.internal.jpa2.context.java.NullJavaOrderColumn2_0; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.JpaFactory2_0; +import org.eclipse.jpt.core.jpa2.context.Orderable2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaOrderColumn2_0; +import org.eclipse.jpt.core.jpa2.context.java.JavaOrderable2_0; +import org.eclipse.jpt.core.jpa2.resource.java.OrderColumn2_0Annotation; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.resource.java.OrderByAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericJavaOrderable + extends AbstractJavaJpaContextNode + implements JavaOrderable2_0 +{ + + protected String specifiedOrderBy = null; + protected boolean noOrdering = false; + protected boolean pkOrdering = false; + protected boolean customOrdering = false; + + //JPA 2.0 + protected final Orderable.Owner owner; //the owner is only used for 2.0 projects + protected boolean orderColumnOrdering = false; + protected final JavaOrderColumn2_0 orderColumn; + + public GenericJavaOrderable(JavaAttributeMapping parent, Orderable.Owner owner) { + super(parent); + this.owner = owner; + this.orderColumn = buildOrderColumn(); + } + + public void initialize() { + this.initializeOrdering(); + } + + public void update() { + this.updateOrdering(); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + protected JavaPersistentAttribute getPersistentAttribute() { + return getParent().getPersistentAttribute(); + } + + protected JavaResourcePersistentAttribute getResourcePersistentAttribute() { + return this.getPersistentAttribute().getResourcePersistentAttribute(); + } + + + // ********** Orderable2_0 implementation ********** + + public String getDefaultTableName() { + return getOwner().getTableName(); + } + + /** + * Only call this for 2.0 projects + */ + protected Orderable2_0.Owner getOwner() { + return (Orderable2_0.Owner) this.owner; + } + + // ********** order by ********** + + public String getSpecifiedOrderBy() { + return this.specifiedOrderBy; + } + + public void setSpecifiedOrderBy(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + if (orderBy == null) { + if (orderByAnnotation != null) { + this.removeOrderByAnnotation(); + } + } else { + if (orderByAnnotation == null) { + orderByAnnotation = this.addOrderByAnnotation(); + } + orderByAnnotation.setValue(orderBy); + } + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected void setSpecifiedOrderBy_(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected void initializeOrdering() { + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + OrderColumn2_0Annotation orderColumnAnnotation = this.getOrderColumnAnnotation(); + if (orderByAnnotation == null && orderColumnAnnotation == null) { + this.noOrdering = true; + } else if (orderByAnnotation != null){ + this.specifiedOrderBy = orderByAnnotation.getValue(); + if (this.specifiedOrderBy == null) { + this.pkOrdering = true; + } else { + this.customOrdering = true; + } + } else { + this.orderColumnOrdering = true; + } + this.orderColumn.initialize(getResourcePersistentAttribute()); + } + + protected void updateOrdering() { + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + OrderColumn2_0Annotation orderColumnAnnotation = this.getOrderColumnAnnotation(); + if (orderByAnnotation == null && orderColumnAnnotation == null) { + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(true); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + } else if (orderByAnnotation != null) { + String ob = orderByAnnotation.getValue(); + this.setSpecifiedOrderBy_(ob); + this.setNoOrdering_(false); + this.setPkOrdering_(ob == null); + this.setCustomOrdering_(ob != null); + this.setOrderColumnOrdering_(false); + } else { + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(true); + } + this.orderColumn.update(getResourcePersistentAttribute()); + } + + protected OrderByAnnotation getOrderByAnnotation() { + return (OrderByAnnotation) this.getResourcePersistentAttribute().getAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + protected OrderByAnnotation addOrderByAnnotation() { + return (OrderByAnnotation) this.getResourcePersistentAttribute().addAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + protected void removeOrderByAnnotation() { + this.getResourcePersistentAttribute().removeAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + + // ********** no ordering ********** + + public boolean isNoOrdering() { + return this.noOrdering; + } + + public void setNoOrdering(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + if (noOrdering) { + if (this.getOrderByAnnotation() != null) { + this.removeOrderByAnnotation(); + } + if (this.getOrderColumnAnnotation() != null) { + this.removeOrderColumnAnnotation(); + } + } else { + // the 'noOrdering' flag is cleared as a + // side-effect of setting the other flags, + // via a call to #setNoOrdering_(boolean) + } + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + protected void setNoOrdering_(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + + // ********** pk ordering ********** + + public boolean isPkOrdering() { + return this.pkOrdering; + } + + public void setPkOrdering(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + if (pkOrdering) { + if (orderByAnnotation == null) { + this.addOrderByAnnotation(); + } else { + orderByAnnotation.setValue(null); + } + } else { + // the 'pkOrdering' flag is cleared as a + // side-effect of setting the other flags, + // via a call to #setPkOrdering_(boolean) + } + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + protected void setPkOrdering_(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + + // ********** custom ordering ********** + + public boolean isCustomOrdering() { + return this.customOrdering; + } + + public void setCustomOrdering(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + if (customOrdering) { + this.setSpecifiedOrderBy(""); //$NON-NLS-1$ + } else { + // the 'customOrdering' flag is cleared as a + // side-effect of setting the other flags, + // via a call to #setCustomOrdering_(boolean) + } + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + protected void setCustomOrdering_(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + // ********** order column 2.0 ********** + + protected JavaOrderColumn2_0 buildOrderColumn() { + return this.isJpa2_0Compatible() ? + ((JpaFactory2_0) getJpaFactory()).buildJavaOrderColumn(this, new OrderColumnOwner()) : + new NullJavaOrderColumn2_0(this, new OrderColumnOwner()); + } + + public boolean isOrderColumnOrdering() { + return this.orderColumnOrdering; + } + + public void setOrderColumnOrdering(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + OrderColumn2_0Annotation orderColumnAnnotation = this.getOrderColumnAnnotation(); + if (orderColumnOrdering) { + if (orderColumnAnnotation == null) { + this.addOrderColumnAnnotation(); + } + this.removeOrderByAnnotation(); + } else { + removeOrderColumnAnnotation(); + } + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + protected void setOrderColumnOrdering_(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + public JavaOrderColumn2_0 getOrderColumn() { + return this.orderColumn; + } + + protected OrderColumn2_0Annotation getOrderColumnAnnotation() { + return (OrderColumn2_0Annotation) this.getResourcePersistentAttribute().getAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + protected OrderColumn2_0Annotation addOrderColumnAnnotation() { + return (OrderColumn2_0Annotation) this.getResourcePersistentAttribute().addAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + protected void removeOrderColumnAnnotation() { + this.getResourcePersistentAttribute().removeAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + result = this.getOrderColumn().javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + return null; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + TextRange textRange = this.getOrderByAnnotationTextRange(astRoot); + return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot); + } + + protected TextRange getOrderByAnnotationTextRange(CompilationUnit astRoot) { + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + return (orderByAnnotation == null) ? null : orderByAnnotation.getTextRange(astRoot); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + if (getOrderColumnAnnotation() != null && getOrderByAnnotation() != null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ORDER_COLUMN_AND_ORDER_BY_BOTH_SPECIFIED, + new String[] {getPersistentAttribute().getName()}, + this.getParent(), + this.getOrderByAnnotationTextRange(astRoot) + ) + ); + } + if (isOrderColumnOrdering()) { + //TODO validation message if type is not List + this.getOrderColumn().validate(messages, reporter, astRoot); + } + } + + // ********** JavaNamedColumn.Owner implementation- JPA 2.0 ********** + + protected class OrderColumnOwner implements JavaNamedColumn.Owner { + + public String getDefaultTableName() { + return GenericJavaOrderable.this.getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public String getDefaultColumnName() { + return getPersistentAttribute().getName() + "_ORDER"; //$NON-NLS-1$ + } + + public TypeMapping getTypeMapping() { + return getPersistentAttribute().getOwningTypeMapping(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaOrderable.this.getValidationTextRange(astRoot); + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ORDER_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentAttribute.java new file mode 100644 index 0000000000..7d052c2afb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentAttribute.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.PersistentType; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaPersistentAttribute; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; + +/** + * Generic Java persistent attribute + */ +public class GenericJavaPersistentAttribute + extends AbstractJavaPersistentAttribute +{ + + public GenericJavaPersistentAttribute(PersistentType parent, JavaResourcePersistentAttribute jrpa) { + super(parent, jrpa); + } + + + // ********** AccessHolder implementation ********** + + /** + * GenericJavaPersistentAttribute does not support specified access (no access element in 1.0), so we return null + */ + public AccessType getSpecifiedAccess() { + return null; + } + + public void setSpecifiedAccess(AccessType specifiedAccess) { + throw new UnsupportedOperationException(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentType.java new file mode 100644 index 0000000000..a18bb0ff37 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPersistentType.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.PersistentType; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaPersistentType; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; + +/** + * JPA 1.0 Java persistent type. + * The specified access is always null. + */ +public class GenericJavaPersistentType + extends AbstractJavaPersistentType +{ + + public GenericJavaPersistentType(PersistentType.Owner parent, JavaResourcePersistentType jrpt) { + super(parent, jrpt); + } + + + // ********** access ********** + + /** + * GenericJavaPersistentType does not support specified access (no Access + * annotation in 1.0), so we return null + */ + @Override + protected AccessType buildSpecifiedAccess() { + return null; + } + + /** + * GenericJavaPersistentType does not support specified access + * (no Access annotation in 1.0) + */ + public void setSpecifiedAccess(AccessType specifiedAccess) { + throw new UnsupportedOperationException(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..6a66e6da61 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java @@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.java.JavaBaseJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaNamedColumn; +import org.eclipse.jpt.core.resource.java.PrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + + +public class GenericJavaPrimaryKeyJoinColumn extends AbstractJavaNamedColumn<PrimaryKeyJoinColumnAnnotation> + implements JavaPrimaryKeyJoinColumn +{ + protected String specifiedReferencedColumnName; + + protected String defaultReferencedColumnName; + + public GenericJavaPrimaryKeyJoinColumn(JavaJpaContextNode parent, JavaBaseJoinColumn.Owner owner) { + super(parent, owner); + } + + @Override + public void initialize(PrimaryKeyJoinColumnAnnotation column) { + super.initialize(column); + this.specifiedReferencedColumnName = this.getResourceReferencedColumnName(); + this.defaultReferencedColumnName = this.buildDefaultReferencedColumnName(); + } + + @Override + public void update(PrimaryKeyJoinColumnAnnotation resourceColumn) { + super.update(resourceColumn); + this.setSpecifiedReferencedColumnName_(this.getResourceReferencedColumnName()); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + //************** JavaNamedColumn implementation *************** + @Override + public JavaBaseJoinColumn.Owner getOwner() { + return (JavaBaseJoinColumn.Owner) super.getOwner(); + } + + //************** BaseJoinColumn implementation *************** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName == null) ? this.defaultReferencedColumnName : this.specifiedReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + getResourceColumn().setReferencedColumnName(newSpecifiedReferencedColumnName); + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + protected void setSpecifiedReferencedColumnName_(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String newDefaultReferencedColumnName) { + String oldDefaultReferencedColumnName = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = newDefaultReferencedColumnName; + firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, oldDefaultReferencedColumnName, newDefaultReferencedColumnName); + } + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + @Override + public String getTable() { + return getOwner().getDefaultTableName(); + } + + public Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public Table getReferencedColumnDbTable() { + return getOwner().getReferencedColumnDbTable(); + } + + public boolean referencedColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.getResourceColumn().referencedColumnNameTouches(pos, astRoot); + } + + @Override + public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.referencedColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateReferencedColumnNames(filter).iterator(); + } + return null; + } + + private Iterable<String> getJavaCandidateReferencedColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateReferencedColumnNames(filter)); + } + + private Iterable<String> getCandidateReferencedColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateReferencedColumnNames(), filter); + } + + private Iterable<String> getCandidateReferencedColumnNames() { + Table table = this.getOwner().getReferencedColumnDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + public boolean isReferencedColumnResolved() { + return getReferencedDbColumn() != null; + } + + public TextRange getReferencedColumnNameTextRange(CompilationUnit astRoot) { + TextRange textRange = this.getResourceColumn().getReferencedColumnNameTextRange(astRoot); + return textRange != null ? textRange : getValidationTextRange(astRoot); + } + + protected String getResourceReferencedColumnName() { + return getResourceColumn().getReferencedColumnName(); + } + + //TODO not correct when we start supporting primaryKeyJoinColumns in 1-1 mappings + protected String buildDefaultReferencedColumnName() { + return buildDefaultName(); + } + + @Override + public void toString(StringBuilder sb) { + super.toString(sb); + sb.append("=>"); //$NON-NLS-1$ + sb.append(this.getReferencedColumnName()); + } + + @Override + //this method will only be called if the table validates correctly + protected void validateName(List<IMessage> messages, CompilationUnit astRoot) { + this.validateJoinColumnName(messages, astRoot); + this.validateReferencedColumnName(messages, astRoot); + } + + protected void validateJoinColumnName(List<IMessage> messages, CompilationUnit astRoot) { + if (getSpecifiedName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedNameMultipleJoinColumnsMessage(astRoot)); + } + else if (this.getName() != null){ + super.validateName(messages, astRoot); + } + //If the name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected void validateReferencedColumnName(List<IMessage> messages, CompilationUnit astRoot) { + if (getSpecifiedReferencedColumnName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(astRoot)); + } + else if (this.getReferencedColumnName() != null) { + if (this.getReferencedColumnDbTable() != null && ! this.isReferencedColumnResolved()) { + messages.add(getOwner().buildUnresolvedReferencedColumnNameMessage(this, this.getReferencedColumnNameTextRange(astRoot))); + } + } + //If the referenced column name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(CompilationUnit astRoot) { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(this, getNameTextRange(astRoot)); + } + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(CompilationUnit astRoot) { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(this, getReferencedColumnNameTextRange(astRoot)); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryContainer.java new file mode 100644 index 0000000000..3baaedc7bc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryContainer.java @@ -0,0 +1,293 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.NamedNativeQuery; +import org.eclipse.jpt.core.context.NamedQuery; +import org.eclipse.jpt.core.context.Query; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaNamedNativeQuery; +import org.eclipse.jpt.core.context.java.JavaNamedQuery; +import org.eclipse.jpt.core.context.java.JavaQuery; +import org.eclipse.jpt.core.context.java.JavaQueryContainer; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.resource.java.NamedNativeQueriesAnnotation; +import org.eclipse.jpt.core.resource.java.NamedNativeQueryAnnotation; +import org.eclipse.jpt.core.resource.java.NamedQueriesAnnotation; +import org.eclipse.jpt.core.resource.java.NamedQueryAnnotation; +import org.eclipse.jpt.core.resource.java.NestableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaQueryContainer extends AbstractJavaJpaContextNode + implements JavaQueryContainer +{ + protected JavaResourcePersistentMember javaResourcePersistentMember; + + protected final List<JavaNamedQuery> namedQueries; + + protected final List<JavaNamedNativeQuery> namedNativeQueries; + + public GenericJavaQueryContainer(JavaJpaContextNode parent) { + super(parent); + this.namedQueries = new ArrayList<JavaNamedQuery>(); + this.namedNativeQueries = new ArrayList<JavaNamedNativeQuery>(); + } + + @Override + public JavaJpaContextNode getParent() { + return (JavaJpaContextNode) super.getParent(); + } + + + public ListIterator<JavaNamedQuery> namedQueries() { + return new CloneListIterator<JavaNamedQuery>(this.namedQueries); + } + + public int namedQueriesSize() { + return this.namedQueries.size(); + } + + public JavaNamedQuery addNamedQuery(int index) { + JavaNamedQuery namedQuery = getJpaFactory().buildJavaNamedQuery(this); + this.namedQueries.add(index, namedQuery); + NamedQueryAnnotation namedQueryAnnotation = + (NamedQueryAnnotation) this.javaResourcePersistentMember. + addAnnotation( + index, NamedQueryAnnotation.ANNOTATION_NAME, + NamedQueriesAnnotation.ANNOTATION_NAME); + namedQuery.initialize(namedQueryAnnotation); + fireItemAdded(NAMED_QUERIES_LIST, index, namedQuery); + return namedQuery; + } + + protected void addNamedQuery(int index, JavaNamedQuery namedQuery) { + addItemToList(index, namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + protected void addNamedQuery(JavaNamedQuery namedQuery) { + this.addNamedQuery(this.namedQueries.size(), namedQuery); + } + + public void removeNamedQuery(NamedQuery namedQuery) { + removeNamedQuery(this.namedQueries.indexOf(namedQuery)); + } + + public void removeNamedQuery(int index) { + JavaNamedQuery removedNamedQuery = this.namedQueries.remove(index); + this.javaResourcePersistentMember.removeAnnotation( + index, NamedQueryAnnotation.ANNOTATION_NAME, NamedQueriesAnnotation.ANNOTATION_NAME); + fireItemRemoved(NAMED_QUERIES_LIST, index, removedNamedQuery); + } + + protected void removeNamedQuery_(JavaNamedQuery namedQuery) { + removeItemFromList(namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + public void moveNamedQuery(int targetIndex, int sourceIndex) { + CollectionTools.move(this.namedQueries, targetIndex, sourceIndex); + this.javaResourcePersistentMember.moveAnnotation( + targetIndex, sourceIndex, NamedQueriesAnnotation.ANNOTATION_NAME); + fireItemMoved(NAMED_QUERIES_LIST, targetIndex, sourceIndex); + } + + public ListIterator<JavaNamedNativeQuery> namedNativeQueries() { + return new CloneListIterator<JavaNamedNativeQuery>(this.namedNativeQueries); + } + + public int namedNativeQueriesSize() { + return this.namedNativeQueries.size(); + } + + public JavaNamedNativeQuery addNamedNativeQuery(int index) { + JavaNamedNativeQuery namedNativeQuery = getJpaFactory().buildJavaNamedNativeQuery(this); + this.namedNativeQueries.add(index, namedNativeQuery); + NamedNativeQueryAnnotation namedNativeQueryAnnotation = + (NamedNativeQueryAnnotation) this.javaResourcePersistentMember. + addAnnotation( + index, NamedNativeQueryAnnotation.ANNOTATION_NAME, + NamedNativeQueriesAnnotation.ANNOTATION_NAME); + namedNativeQuery.initialize(namedNativeQueryAnnotation); + fireItemAdded(NAMED_NATIVE_QUERIES_LIST, index, namedNativeQuery); + return namedNativeQuery; + } + + protected void addNamedNativeQuery(int index, JavaNamedNativeQuery namedNativeQuery) { + addItemToList(index, namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + protected void addNamedNativeQuery(JavaNamedNativeQuery namedNativeQuery) { + this.addNamedNativeQuery(this.namedNativeQueries.size(), namedNativeQuery); + } + + public void removeNamedNativeQuery(NamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + public void removeNamedNativeQuery(int index) { + JavaNamedNativeQuery removedNamedNativeQuery = this.namedNativeQueries.remove(index); + this.javaResourcePersistentMember.removeAnnotation( + index, NamedNativeQueryAnnotation.ANNOTATION_NAME, + NamedNativeQueriesAnnotation.ANNOTATION_NAME); + fireItemRemoved(NAMED_NATIVE_QUERIES_LIST, index, removedNamedNativeQuery); + } + + protected void removeNamedNativeQuery_(JavaNamedNativeQuery namedNativeQuery) { + removeItemFromList(namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + public void moveNamedNativeQuery(int targetIndex, int sourceIndex) { + CollectionTools.move(this.namedNativeQueries, targetIndex, sourceIndex); + this.javaResourcePersistentMember.moveAnnotation( + targetIndex, sourceIndex, NamedNativeQueriesAnnotation.ANNOTATION_NAME); + fireItemMoved(NAMED_NATIVE_QUERIES_LIST, targetIndex, sourceIndex); + } + + + + public void initialize(JavaResourcePersistentMember jrpm) { + this.javaResourcePersistentMember = jrpm; + this.initializeNamedQueries(); + this.initializeNamedNativeQueries(); + } + + protected void initializeNamedQueries() { + for (Iterator<NestableAnnotation> stream = this.javaResourcePersistentMember. + annotations( + NamedQueryAnnotation.ANNOTATION_NAME, + NamedQueriesAnnotation.ANNOTATION_NAME); + stream.hasNext(); ) { + this.namedQueries.add(buildNamedQuery((NamedQueryAnnotation) stream.next())); + } + } + + protected void initializeNamedNativeQueries() { + for (Iterator<NestableAnnotation> stream = this.javaResourcePersistentMember. + annotations( + NamedNativeQueryAnnotation.ANNOTATION_NAME, + NamedNativeQueriesAnnotation.ANNOTATION_NAME); + stream.hasNext(); ) { + this.namedNativeQueries.add(buildNamedNativeQuery((NamedNativeQueryAnnotation) stream.next())); + } + } + + protected JavaNamedQuery buildNamedQuery(NamedQueryAnnotation namedQueryResource) { + JavaNamedQuery namedQuery = getJpaFactory().buildJavaNamedQuery(this); + namedQuery.initialize(namedQueryResource); + return namedQuery; + } + + protected JavaNamedNativeQuery buildNamedNativeQuery(NamedNativeQueryAnnotation namedNativeQueryResource) { + JavaNamedNativeQuery namedNativeQuery = getJpaFactory().buildJavaNamedNativeQuery(this); + namedNativeQuery.initialize(namedNativeQueryResource); + return namedNativeQuery; + } + + public void update(JavaResourcePersistentMember jrpm) { + this.javaResourcePersistentMember = jrpm; + this.updateNamedQueries(); + this.updateNamedNativeQueries(); + } + + protected void updateNamedQueries() { + ListIterator<JavaNamedQuery> queries = namedQueries(); + Iterator<NestableAnnotation> resourceNamedQueries = + this.javaResourcePersistentMember.annotations( + NamedQueryAnnotation.ANNOTATION_NAME, + NamedQueriesAnnotation.ANNOTATION_NAME); + + while (queries.hasNext()) { + JavaNamedQuery namedQuery = queries.next(); + if (resourceNamedQueries.hasNext()) { + namedQuery.update((NamedQueryAnnotation) resourceNamedQueries.next()); + } + else { + removeNamedQuery_(namedQuery); + } + } + + while (resourceNamedQueries.hasNext()) { + addNamedQuery(buildNamedQuery((NamedQueryAnnotation) resourceNamedQueries.next())); + } + } + + protected void updateNamedNativeQueries() { + ListIterator<JavaNamedNativeQuery> queries = namedNativeQueries(); + Iterator<NestableAnnotation> resourceNamedNativeQueries = + this.javaResourcePersistentMember.annotations( + NamedNativeQueryAnnotation.ANNOTATION_NAME, + NamedNativeQueriesAnnotation.ANNOTATION_NAME); + + while (queries.hasNext()) { + JavaNamedNativeQuery namedQuery = queries.next(); + if (resourceNamedNativeQueries.hasNext()) { + namedQuery.update((NamedNativeQueryAnnotation) resourceNamedNativeQueries.next()); + } + else { + removeNamedNativeQuery_(namedQuery); + } + } + + while (resourceNamedNativeQueries.hasNext()) { + addNamedNativeQuery(buildNamedNativeQuery((NamedNativeQueryAnnotation) resourceNamedNativeQueries.next())); + } + } + + + //********** Validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.validateQueries(messages, astRoot); + } + + protected void validateQueries(List<IMessage> messages, CompilationUnit astRoot) { + for (Iterator<JavaQuery> localQueries = this.queries(); localQueries.hasNext(); ) { + JavaQuery localQuery = localQueries.next(); + for (Iterator<Query> globalQueries = this.getPersistenceUnit().queries(); globalQueries.hasNext(); ) { + if (localQuery.duplicates(globalQueries.next())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_DUPLICATE_NAME, + new String[] {localQuery.getName()}, + localQuery, + localQuery.getNameTextRange(astRoot) + ) + ); + } + } + } + } + + + @SuppressWarnings("unchecked") + public Iterator<JavaQuery> queries() { + return new CompositeIterator<JavaQuery>(this.namedNativeQueries(), this.namedQueries()); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.javaResourcePersistentMember.getTextRange(astRoot); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryHint.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryHint.java new file mode 100644 index 0000000000..e785903ef3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaQueryHint.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.QueryHint; +import org.eclipse.jpt.core.context.java.JavaQuery; +import org.eclipse.jpt.core.context.java.JavaQueryHint; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.QueryHintAnnotation; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaQueryHint extends AbstractJavaJpaContextNode implements JavaQueryHint +{ + protected String name; + + protected String value; + + protected QueryHintAnnotation resourceQueryHint; + + public GenericJavaQueryHint(JavaQuery parent) { + super(parent); + } + + public String getName() { + return this.name; + } + + public void setName(String newName) { + String oldName = this.name; + this.name = newName; + this.resourceQueryHint.setName(newName); + firePropertyChanged(QueryHint.NAME_PROPERTY, oldName, newName); + } + + public String getValue() { + return this.value; + } + + public void setValue(String newValue) { + String oldValue = this.value; + this.value = newValue; + this.resourceQueryHint.setValue(newValue); + firePropertyChanged(QueryHint.VALUE_PROPERTY, oldValue, newValue); + } + + + public void initialize(QueryHintAnnotation resourceQueryHint) { + this.resourceQueryHint = resourceQueryHint; + this.name = resourceQueryHint.getName(); + this.value = resourceQueryHint.getValue(); + } + + public void update(QueryHintAnnotation resourceQueryHint) { + this.resourceQueryHint = resourceQueryHint; + this.setName(resourceQueryHint.getName()); + this.setValue(resourceQueryHint.getValue()); + } + + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.resourceQueryHint.getTextRange(astRoot); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java new file mode 100644 index 0000000000..51691fe363 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaReferenceTable.java @@ -0,0 +1,365 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaReferenceTable; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable; +import org.eclipse.jpt.core.internal.resource.java.NullJoinColumnAnnotation; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JoinColumnAnnotation; +import org.eclipse.jpt.core.resource.java.ReferenceTableAnnotation; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java join table + */ +public abstract class GenericJavaReferenceTable + extends AbstractJavaTable + implements JavaReferenceTable +{ + + protected JavaJoinColumn defaultJoinColumn; + + protected final Vector<JavaJoinColumn> specifiedJoinColumns = new Vector<JavaJoinColumn>(); + protected final JavaJoinColumn.Owner joinColumnOwner; + + + protected GenericJavaReferenceTable(JavaJpaContextNode parent) { + super(parent); + this.joinColumnOwner = this.buildJoinColumnOwner(); + } + + protected abstract JavaJoinColumn.Owner buildJoinColumnOwner(); + + public void initialize(ReferenceTableAnnotation referenceTableAnnotation) { + super.initialize(referenceTableAnnotation); + this.initializeSpecifiedJoinColumns(referenceTableAnnotation); + this.initializeDefaultJoinColumn(referenceTableAnnotation); + } + + public void update(ReferenceTableAnnotation referenceTableAnnotation) { + super.update(referenceTableAnnotation); + this.updateSpecifiedJoinColumns(referenceTableAnnotation); + this.updateDefaultJoinColumn(referenceTableAnnotation); + } + + + // ********** AbstractJavaTable implementation ********** + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + @Override + protected abstract ReferenceTableAnnotation getAnnotation(); + + + // ********** Table implementation ********** + + public boolean isResourceSpecified() { + return this.getAnnotation().isSpecified(); + } + + + // ********** join columns ********** + + public ListIterator<JavaJoinColumn> joinColumns() { + return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumns() : this.defaultJoinColumns(); + } + + public int joinColumnsSize() { + return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumnsSize() : this.defaultJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedJoinColumn() { + MappingTools.convertReferenceTableDefaultToSpecifiedJoinColumn(this); + } + + protected JavaJoinColumn buildJoinColumn(JoinColumnAnnotation joinColumnAnnotation) { + return this.buildJoinColumn(joinColumnAnnotation, this.joinColumnOwner); + } + + + // ********** default join column ********** + + public JavaJoinColumn getDefaultJoinColumn() { + return this.defaultJoinColumn; + } + + protected void setDefaultJoinColumn(JavaJoinColumn defaultJoinColumn) { + JavaJoinColumn old = this.defaultJoinColumn; + this.defaultJoinColumn = defaultJoinColumn; + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, old, defaultJoinColumn); + } + + protected ListIterator<JavaJoinColumn> defaultJoinColumns() { + if (this.defaultJoinColumn != null) { + return new SingleElementListIterator<JavaJoinColumn>(this.defaultJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultJoinColumnsSize() { + return (this.defaultJoinColumn == null) ? 0 : 1; + } + + protected void initializeDefaultJoinColumn(ReferenceTableAnnotation referenceTableAnnotation) { + if (this.shouldBuildDefaultJoinColumn()) { + this.defaultJoinColumn = this.buildJoinColumn(new NullJoinColumnAnnotation(referenceTableAnnotation)); + } + } + + protected void updateDefaultJoinColumn(ReferenceTableAnnotation referenceTableAnnotation) { + if (this.shouldBuildDefaultJoinColumn()) { + if (this.defaultJoinColumn == null) { + this.setDefaultJoinColumn(this.buildJoinColumn(new NullJoinColumnAnnotation(referenceTableAnnotation))); + } else { + this.defaultJoinColumn.update(new NullJoinColumnAnnotation(referenceTableAnnotation)); + } + } else { + this.setDefaultJoinColumn(null); + } + } + + protected boolean shouldBuildDefaultJoinColumn() { + return ! this.hasSpecifiedJoinColumns(); + } + + + // ********** specified join columns ********** + + public ListIterator<JavaJoinColumn> specifiedJoinColumns() { + return new CloneListIterator<JavaJoinColumn>(this.specifiedJoinColumns); + } + + public int specifiedJoinColumnsSize() { + return this.specifiedJoinColumns.size(); + } + + public boolean hasSpecifiedJoinColumns() { + return this.specifiedJoinColumns.size() != 0; + } + + public JavaJoinColumn addSpecifiedJoinColumn(int index) { + // Clear out the default now so it doesn't get removed during an update and + // cause change notifications to be sent to the UI in the wrong order. + // If the default is already null, nothing will happen. + JoinColumn oldDefault = this.defaultJoinColumn; + this.defaultJoinColumn = null; + + JavaJoinColumn joinColumn = this.getJpaFactory().buildJavaJoinColumn(this, this.joinColumnOwner); + this.specifiedJoinColumns.add(index, joinColumn); + ReferenceTableAnnotation referenceTableAnnotation = this.getAnnotation(); + JoinColumnAnnotation joinColumnAnnotation = referenceTableAnnotation.addJoinColumn(index); + joinColumn.initialize(joinColumnAnnotation); + this.fireItemAdded(SPECIFIED_JOIN_COLUMNS_LIST, index, joinColumn); + + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, oldDefault, null); + return joinColumn; + } + + protected void addSpecifiedJoinColumn(int index, JavaJoinColumn joinColumn) { + this.addItemToList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedJoinColumn(JavaJoinColumn joinColumn) { + this.addSpecifiedJoinColumn(this.specifiedJoinColumns.size(), joinColumn); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedJoinColumn(this.specifiedJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedJoinColumn(int index) { + JavaJoinColumn removedJoinColumn = this.specifiedJoinColumns.remove(index); + if ( ! this.hasSpecifiedJoinColumns()) { + //create the defaultJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultJoinColumn = this.buildJoinColumn(new NullJoinColumnAnnotation(this.getAnnotation())); + } + this.getAnnotation().removeJoinColumn(index); + this.fireItemRemoved(SPECIFIED_JOIN_COLUMNS_LIST, index, removedJoinColumn); + if (this.defaultJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, null, this.defaultJoinColumn); + } + } + + protected void removeSpecifiedJoinColumn_(JavaJoinColumn joinColumn) { + this.removeItemFromList(joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedJoinColumns, targetIndex, sourceIndex); + this.getAnnotation().moveJoinColumn(targetIndex, sourceIndex); + this.fireItemMoved(SPECIFIED_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + public void clearSpecifiedJoinColumns() { + // for now, we have to remove annotations one at a time... + for (int i = this.specifiedJoinColumns.size(); i-- > 0; ) { + this.removeSpecifiedJoinColumn(i); + } + } + + protected void initializeSpecifiedJoinColumns(ReferenceTableAnnotation referenceTableAnnotation) { + for (ListIterator<JoinColumnAnnotation> stream = referenceTableAnnotation.joinColumns(); stream.hasNext(); ) { + this.specifiedJoinColumns.add(this.buildJoinColumn(stream.next())); + } + } + + protected void updateSpecifiedJoinColumns(ReferenceTableAnnotation referenceTableAnnotation) { + ListIterator<JavaJoinColumn> joinColumns = this.specifiedJoinColumns(); + ListIterator<JoinColumnAnnotation> joinColumnAnnotations = referenceTableAnnotation.joinColumns(); + + while (joinColumns.hasNext()) { + JavaJoinColumn joinColumn = joinColumns.next(); + if (joinColumnAnnotations.hasNext()) { + joinColumn.update(joinColumnAnnotations.next()); + } else { + this.removeSpecifiedJoinColumn_(joinColumn); + } + } + + while (joinColumnAnnotations.hasNext()) { + this.addSpecifiedJoinColumn(this.buildJoinColumn(joinColumnAnnotations.next())); + } + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaJoinColumn column : CollectionTools.iterable(this.joinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + // ********** misc ********** + + protected JavaJoinColumn buildJoinColumn(JoinColumnAnnotation joinColumnAnnotation, JavaJoinColumn.Owner owner) { + JavaJoinColumn joinColumn = this.getJpaFactory().buildJavaJoinColumn(this, owner); + joinColumn.initialize(joinColumnAnnotation); + return joinColumn; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + boolean continueValidating = true; + if (this.shouldValidateAgainstDatabase()) { + continueValidating = this.validateAgainstDatabase(messages, reporter, astRoot); + } + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + this.validateJoinColumns(messages, reporter, astRoot); + } + } + + protected abstract boolean shouldValidateAgainstDatabase(); + + protected boolean validateAgainstDatabase(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + if ( ! this.hasResolvedCatalog()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedCatalogMessageId(), + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange(astRoot) + ) + ); + return false; + } + + if ( ! this.hasResolvedSchema()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedSchemaMessageId(), + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange(astRoot) + ) + ); + return false; + } + + if ( ! this.isResolved()) { + if (getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedNameMessageId(), + new String[] {this.getName()}, + this, + this.getNameTextRange(astRoot)) + ); + } + return false; + } + return true; + } + + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + this.validateJoinColumns(this.joinColumns(), messages, reporter, astRoot); + } + + protected void validateJoinColumns(Iterator<JavaJoinColumn> joinColumns, List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + while (joinColumns.hasNext()) { + joinColumns.next().validate(messages, reporter, astRoot); + } + } + + protected abstract String getUnresolvedCatalogMessageId(); + + protected abstract String getUnresolvedSchemaMessageId(); + + protected abstract String getUnresolvedNameMessageId(); +} + diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java new file mode 100644 index 0000000000..e3a8df4319 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java @@ -0,0 +1,466 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.PrimaryKeyJoinColumn; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaBaseJoinColumn; +import org.eclipse.jpt.core.context.java.JavaEntity; +import org.eclipse.jpt.core.context.java.JavaPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.context.java.JavaSecondaryTable; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable; +import org.eclipse.jpt.core.internal.resource.java.NullPrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.PrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.core.resource.java.SecondaryTableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * + */ +public class GenericJavaSecondaryTable + extends AbstractJavaTable + implements JavaSecondaryTable +{ + protected final List<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns; + protected final JavaBaseJoinColumn.Owner primaryKeyJoinColumnOwner; + + protected JavaPrimaryKeyJoinColumn defaultPrimaryKeyJoinColumn; + + protected SecondaryTableAnnotation resourceSecondaryTable; + + public GenericJavaSecondaryTable(JavaEntity parent) { + super(parent); + this.specifiedPrimaryKeyJoinColumns = new ArrayList<JavaPrimaryKeyJoinColumn>(); + this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner(); + } + + protected JavaBaseJoinColumn.Owner buildPrimaryKeyJoinColumnOwner() { + return new PrimaryKeyJoinColumnOwner(); + } + + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + + //***************** AbstractJavaTable implementation ******************** + + @Override + protected String getAnnotationName() { + return SecondaryTableAnnotation.ANNOTATION_NAME; + } + + @Override + protected SecondaryTableAnnotation getAnnotation() { + return this.resourceSecondaryTable; + } + + public boolean isResourceSpecified() { + return true; + } + + // a secondary table doesn't have a default name + @Override + protected String buildDefaultName() { + return null; + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + //***************** ISecondaryTable implementation ******************** + + public ListIterator<JavaPrimaryKeyJoinColumn> primaryKeyJoinColumns() { + return this.containsSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumns() : this.defaultPrimaryKeyJoinColumns(); + } + + public int primaryKeyJoinColumnsSize() { + return this.containsSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumnsSize() : this.defaultPrimaryKeyJoinColumnsSize(); + } + + public ListIterator<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns() { + return new CloneListIterator<JavaPrimaryKeyJoinColumn>(this.specifiedPrimaryKeyJoinColumns); + } + + public int specifiedPrimaryKeyJoinColumnsSize() { + return this.specifiedPrimaryKeyJoinColumns.size(); + } + + public boolean containsSpecifiedPrimaryKeyJoinColumns() { + return !this.specifiedPrimaryKeyJoinColumns.isEmpty(); + } + + public JavaPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() { + return this.defaultPrimaryKeyJoinColumn; + } + + protected void setDefaultPrimaryKeyJoinColumn(JavaPrimaryKeyJoinColumn newPkJoinColumn) { + JavaPrimaryKeyJoinColumn oldPkJoinColumn = this.defaultPrimaryKeyJoinColumn; + this.defaultPrimaryKeyJoinColumn = newPkJoinColumn; + firePropertyChanged(DEFAULT_PRIMARY_KEY_JOIN_COLUMN, oldPkJoinColumn, newPkJoinColumn); + } + + protected ListIterator<JavaPrimaryKeyJoinColumn> defaultPrimaryKeyJoinColumns() { + if (this.defaultPrimaryKeyJoinColumn != null) { + return new SingleElementListIterator<JavaPrimaryKeyJoinColumn>(this.defaultPrimaryKeyJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultPrimaryKeyJoinColumnsSize() { + return (this.defaultPrimaryKeyJoinColumn == null) ? 0 : 1; + } + + public JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn(int index) { + // Clear out the default now so it doesn't get removed during an update and + // cause change notifications to be sent to the UI in the wrong order. + JavaPrimaryKeyJoinColumn oldDefault = this.defaultPrimaryKeyJoinColumn; + this.defaultPrimaryKeyJoinColumn = null; + + JavaPrimaryKeyJoinColumn pkJoinColumn = this.getJpaFactory().buildJavaPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner); + this.specifiedPrimaryKeyJoinColumns.add(index, pkJoinColumn); + PrimaryKeyJoinColumnAnnotation pkJoinColumnAnnotation = this.resourceSecondaryTable.addPkJoinColumn(index); + pkJoinColumn.initialize(pkJoinColumnAnnotation); + this.fireItemAdded(SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, index, pkJoinColumn); + + this.firePropertyChanged(DEFAULT_PRIMARY_KEY_JOIN_COLUMN, oldDefault, null); + return pkJoinColumn; + } + + protected void addSpecifiedPrimaryKeyJoinColumn(int index, JavaPrimaryKeyJoinColumn primaryKeyJoinColumn) { + addItemToList(index, primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedPrimaryKeyJoinColumn(JavaPrimaryKeyJoinColumn primaryKeyJoinColumn) { + this.addSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.size(), primaryKeyJoinColumn); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(PrimaryKeyJoinColumn joinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(int index) { + JavaPrimaryKeyJoinColumn removedPrimaryKeyJoinColumn = this.specifiedPrimaryKeyJoinColumns.remove(index); + if (!containsSpecifiedPrimaryKeyJoinColumns()) { + //create the defaultJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultPrimaryKeyJoinColumn = buildPrimaryKeyJoinColumn(new NullPrimaryKeyJoinColumnAnnotation(this.resourceSecondaryTable)); + } + this.resourceSecondaryTable.removePkJoinColumn(index); + fireItemRemoved(SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, index, removedPrimaryKeyJoinColumn); + if (this.defaultPrimaryKeyJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(Entity.DEFAULT_PRIMARY_KEY_JOIN_COLUMN, null, this.defaultPrimaryKeyJoinColumn); + } + } + + protected void removeSpecifiedPrimaryKeyJoinColumn_(JavaPrimaryKeyJoinColumn primaryKeyJoinColumn) { + removeItemFromList(primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedPrimaryKeyJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedPrimaryKeyJoinColumns, targetIndex, sourceIndex); + this.resourceSecondaryTable.movePkJoinColumn(targetIndex, sourceIndex); + fireItemMoved(SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + public JavaEntity getJavaEntity() { + return getParent(); + } + + + //********************* updating ************************ + + public void initialize(SecondaryTableAnnotation secondaryTable) { + super.initialize(secondaryTable); + this.resourceSecondaryTable = secondaryTable; + this.initializeSpecifiedPrimaryKeyJoinColumns(secondaryTable); + this.initializeDefaultPrimaryKeyJoinColumn(secondaryTable); + } + + protected void initializeSpecifiedPrimaryKeyJoinColumns(SecondaryTableAnnotation secondaryTable) { + ListIterator<PrimaryKeyJoinColumnAnnotation> annotations = secondaryTable.pkJoinColumns(); + + while(annotations.hasNext()) { + this.specifiedPrimaryKeyJoinColumns.add(buildPrimaryKeyJoinColumn(annotations.next())); + } + } + + protected boolean shouldBuildDefaultPrimaryKeyJoinColumn() { + return !containsSpecifiedPrimaryKeyJoinColumns(); + } + + protected void initializeDefaultPrimaryKeyJoinColumn(SecondaryTableAnnotation secondaryTable) { + if (!shouldBuildDefaultPrimaryKeyJoinColumn()) { + return; + } + this.defaultPrimaryKeyJoinColumn = buildPrimaryKeyJoinColumn(new NullPrimaryKeyJoinColumnAnnotation(secondaryTable)); + } + + + public void update(SecondaryTableAnnotation sta) { + this.resourceSecondaryTable = sta; + super.update(sta); + this.updateSpecifiedPrimaryKeyJoinColumns(sta); + this.updateDefaultPrimaryKeyJoinColumn(sta); + } + + protected void updateSpecifiedPrimaryKeyJoinColumns(SecondaryTableAnnotation sta) { + ListIterator<JavaPrimaryKeyJoinColumn> primaryKeyJoinColumns = specifiedPrimaryKeyJoinColumns(); + ListIterator<PrimaryKeyJoinColumnAnnotation> resourcePrimaryKeyJoinColumns = sta.pkJoinColumns(); + + while (primaryKeyJoinColumns.hasNext()) { + JavaPrimaryKeyJoinColumn primaryKeyJoinColumn = primaryKeyJoinColumns.next(); + if (resourcePrimaryKeyJoinColumns.hasNext()) { + primaryKeyJoinColumn.update(resourcePrimaryKeyJoinColumns.next()); + } + else { + removeSpecifiedPrimaryKeyJoinColumn_(primaryKeyJoinColumn); + } + } + + while (resourcePrimaryKeyJoinColumns.hasNext()) { + addSpecifiedPrimaryKeyJoinColumn(buildPrimaryKeyJoinColumn(resourcePrimaryKeyJoinColumns.next())); + } + } + + protected void updateDefaultPrimaryKeyJoinColumn(SecondaryTableAnnotation sta) { + if (!shouldBuildDefaultPrimaryKeyJoinColumn()) { + setDefaultPrimaryKeyJoinColumn(null); + return; + } + if (getDefaultPrimaryKeyJoinColumn() == null) { + this.setDefaultPrimaryKeyJoinColumn(buildPrimaryKeyJoinColumn(new NullPrimaryKeyJoinColumnAnnotation(sta))); + } + else { + this.defaultPrimaryKeyJoinColumn.update(new NullPrimaryKeyJoinColumnAnnotation(sta)); + } + } + + protected JavaPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(PrimaryKeyJoinColumnAnnotation resourcePrimaryKeyJoinColumn) { + JavaPrimaryKeyJoinColumn primaryKeyJoinColumn = getJpaFactory().buildJavaPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner); + primaryKeyJoinColumn.initialize(resourcePrimaryKeyJoinColumn); + return primaryKeyJoinColumn; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + boolean continueValidating = true; + if (this.connectionProfileIsActive()) { + continueValidating = this.validateAgainstDatabase(messages, astRoot); + } + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + for (Iterator<JavaPrimaryKeyJoinColumn> stream = this.primaryKeyJoinColumns(); stream.hasNext(); ) { + stream.next().validate(messages, reporter, astRoot); + } + } + } + + protected boolean validateAgainstDatabase(List<IMessage> messages, CompilationUnit astRoot) { + if ( ! this.hasResolvedCatalog()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG, + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange(astRoot) + ) + ); + return false; + } + + if ( ! this.hasResolvedSchema()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA, + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange(astRoot) + ) + ); + return false; + } + + if ( ! this.isResolved()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME, + new String[] {this.getName()}, + this, + this.getNameTextRange(astRoot) + ) + ); + return false; + } + return true; + } + + + // ********** code completion ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaPrimaryKeyJoinColumn column : CollectionTools.iterable(this.primaryKeyJoinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + public boolean isVirtual() { + return false; + } + + + // ********** PK join column owner adapter ********** + + protected class PrimaryKeyJoinColumnOwner + implements JavaBaseJoinColumn.Owner + { + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaSecondaryTable.this.getValidationTextRange(astRoot); + } + + public TypeMapping getTypeMapping() { + return GenericJavaSecondaryTable.this.getJavaEntity(); + } + + public String getDefaultTableName() { + return GenericJavaSecondaryTable.this.getName(); + } + + public Table getDbTable(String tableName) { + return GenericJavaSecondaryTable.this.getDbTable(); + } + + public Table getReferencedColumnDbTable() { + return getTypeMapping().getPrimaryDbTable(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericJavaSecondaryTable.this.defaultPrimaryKeyJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + if (joinColumnsSize() != 1) { + return null; + } + return getJavaEntity().getPrimaryKeyColumnName(); + + } + + public int joinColumnsSize() { + return GenericJavaSecondaryTable.this.primaryKeyJoinColumnsSize(); + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + if (((BaseJoinColumn) column).isVirtual()) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + if (column.isVirtual()) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java new file mode 100644 index 0000000000..66ff8640b4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaSequenceGenerator; + +/** + * + */ +public class GenericJavaSequenceGenerator extends AbstractJavaSequenceGenerator +{ + + public GenericJavaSequenceGenerator(JavaJpaContextNode parent) { + super(parent); + } + + // ********** database stuff ********** + + /** + * The JPA spec does not allow a sequence to have a schema. + */ + @Override + protected String getSchema() { + return this.getContextDefaultSchema(); + } + + /** + * The JPA spec does not allow a sequence to have a catalog. + */ + @Override + protected String getCatalog() { + return this.getContextDefaultCatalog(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java new file mode 100644 index 0000000000..ec81d5fb15 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTable.java @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.java.JavaEntity; +import org.eclipse.jpt.core.context.java.JavaTable; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaTable; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.resource.java.TableAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaTable + extends AbstractJavaTable + implements JavaTable +{ + protected JavaResourcePersistentMember resourcePersistentMember; + + public GenericJavaTable(JavaEntity parent) { + super(parent); + } + + public void initialize(JavaResourcePersistentMember pr) { + this.resourcePersistentMember = pr; + initialize(getAnnotation()); + } + + //query for the table resource every time on setters. + //call one setter and the tableResource could change. + //You could call more than one setter before this object has received any notification + //from the java resource model + @Override + protected TableAnnotation getAnnotation() { + //TODO get the NullTable from the resource model or build it here in the context model?? + return (TableAnnotation) this.resourcePersistentMember. + getNonNullAnnotation(getAnnotationName()); + } + + public boolean isResourceSpecified() { + return getAnnotation().isSpecified(); + } + + @Override + protected String getAnnotationName() { + return TableAnnotation.ANNOTATION_NAME; + } + + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + protected JavaEntity getJavaEntity() { + return getParent(); + } + + @Override + protected String buildDefaultName() { + return this.getJavaEntity().getDefaultTableName(); + } + + /** + * Just to remember: + * Entity.getDefaultSchema() + * check inheritance - get default schema from root + * EntityMappings.getSchema() + * check for specified schema + * PersistenceUnit.getDefaultSchema() + * OrmPersistenceUnitDefaults.getSchema() + * JpaProject.getDefaultSchema() + * check for user override project setting + * Catalog.getDefaultSchema() + * or + * Database.getDefaultSchema() + */ + @Override + protected String buildDefaultSchema() { + return this.getJavaEntity().getDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getJavaEntity().getDefaultCatalog(); + } + + public void update(JavaResourcePersistentMember jrpm) { + this.resourcePersistentMember = jrpm; + this.update(getAnnotation()); + } + + + //******************* validation ********************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + if (this.connectionProfileIsActive()) { + this.validateAgainstDatabase(messages, astRoot); + } + } + + protected void validateAgainstDatabase(List<IMessage> messages, CompilationUnit astRoot) { + if ( ! this.hasResolvedCatalog()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_CATALOG, + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange(astRoot) + ) + ); + return; + } + + if ( ! this.hasResolvedSchema()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA, + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange(astRoot) + ) + ); + return; + } + + if ( ! this.isResolved()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_NAME, + new String[] {this.getName()}, + this, + this.getNameTextRange(astRoot) + ) + ); + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTableGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTableGenerator.java new file mode 100644 index 0000000000..14d6d12607 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTableGenerator.java @@ -0,0 +1,533 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.UniqueConstraint; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaTableGenerator; +import org.eclipse.jpt.core.context.java.JavaUniqueConstraint; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaGenerator; +import org.eclipse.jpt.core.resource.java.TableGeneratorAnnotation; +import org.eclipse.jpt.core.resource.java.UniqueConstraintAnnotation; +import org.eclipse.jpt.db.Database; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.SchemaContainer; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; + +/** + * + */ +public class GenericJavaTableGenerator + extends AbstractJavaGenerator + implements JavaTableGenerator, UniqueConstraint.Owner +{ + protected String specifiedTable; + protected String defaultTable; + + protected String specifiedSchema; + protected String defaultSchema; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedPkColumnName; + protected String defaultPkColumnName; + + protected String specifiedValueColumnName; + protected String defaultValueColumnName; + + protected String specifiedPkColumnValue; + protected String defaultPkColumnValue; + + protected final List<JavaUniqueConstraint> uniqueConstraints; + + + // ********** constructor ********** + + public GenericJavaTableGenerator(JavaJpaContextNode parent) { + super(parent); + this.uniqueConstraints = new ArrayList<JavaUniqueConstraint>(); + } + + + // ********** table ********** + + public String getTable() { + return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable; + } + + public String getSpecifiedTable() { + return this.specifiedTable; + } + + public void setSpecifiedTable(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.getResourceGenerator().setTable(table); + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + protected void setSpecifiedTable_(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + /** + * The default table is determined by the JPA implementation. + */ + public String getDefaultTable() { + return this.defaultTable; + } + + + // ********** schema ********** + + @Override + public String getSchema() { + return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema; + } + + public String getSpecifiedSchema() { + return this.specifiedSchema; + } + + public void setSpecifiedSchema(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.getResourceGenerator().setSchema(schema); + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + public String getDefaultSchema() { + return this.defaultSchema; + } + + protected void setDefaultSchema(String schema) { + String old = this.defaultSchema; + this.defaultSchema = schema; + this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema); + } + + + // ********** catalog ********** + + @Override + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.getResourceGenerator().setCatalog(catalog); + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + public String getDefaultCatalog() { + return this.defaultCatalog; + } + + protected void setDefaultCatalog(String catalog) { + String old = this.defaultCatalog; + this.defaultCatalog = catalog; + firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog); + } + + + // ********** primary key column name ********** + + public String getPkColumnName() { + return (this.specifiedPkColumnName != null) ? this.specifiedPkColumnName : this.defaultPkColumnName; + } + + public String getSpecifiedPkColumnName() { + return this.specifiedPkColumnName; + } + + public void setSpecifiedPkColumnName(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.getResourceGenerator().setPkColumnName(name); + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + protected void setSpecifiedPkColumnName_(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + /** + * The default primary key column name is determined by the JPA + * implementation. + */ + public String getDefaultPkColumnName() { + return this.defaultPkColumnName; + } + + + // ********** value column name ********** + + public String getValueColumnName() { + return (this.specifiedValueColumnName != null) ? this.specifiedValueColumnName : this.defaultValueColumnName; + } + + public String getSpecifiedValueColumnName() { + return this.specifiedValueColumnName; + } + + public void setSpecifiedValueColumnName(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.getResourceGenerator().setValueColumnName(name); + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + protected void setSpecifiedValueColumnName_(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultValueColumnName() { + return this.defaultValueColumnName; + } + + + // ********** primary key column value ********** + + public String getPkColumnValue() { + return (this.specifiedPkColumnValue != null) ? this.specifiedPkColumnValue : this.defaultPkColumnValue; + } + + public String getSpecifiedPkColumnValue() { + return this.specifiedPkColumnValue; + } + + public void setSpecifiedPkColumnValue(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.getResourceGenerator().setPkColumnValue(value); + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + protected void setSpecifiedPkColumnValue_(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + public String getDefaultPkColumnValue() { + return this.defaultPkColumnValue; + } + + + // ********** unique constraints ********** + + public ListIterator<JavaUniqueConstraint> uniqueConstraints() { + return new CloneListIterator<JavaUniqueConstraint>(this.uniqueConstraints); + } + + public int uniqueConstraintsSize() { + return this.uniqueConstraints.size(); + } + + public JavaUniqueConstraint addUniqueConstraint(int index) { + JavaUniqueConstraint uniqueConstraint = getJpaFactory().buildJavaUniqueConstraint(this, this); + this.uniqueConstraints.add(index, uniqueConstraint); + UniqueConstraintAnnotation uniqueConstraintAnnotation = this.getResourceGenerator().addUniqueConstraint(index); + uniqueConstraint.initialize(uniqueConstraintAnnotation); + this.fireItemAdded(UNIQUE_CONSTRAINTS_LIST, index, uniqueConstraint); + return uniqueConstraint; + } + + public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) { + this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + public void removeUniqueConstraint(int index) { + JavaUniqueConstraint uniqueConstraint = this.uniqueConstraints.remove(index); + this.getResourceGenerator().removeUniqueConstraint(index); + this.fireItemRemoved(UNIQUE_CONSTRAINTS_LIST, index, uniqueConstraint); + } + + public void moveUniqueConstraint(int targetIndex, int sourceIndex) { + CollectionTools.move(this.uniqueConstraints, targetIndex, sourceIndex); + this.getResourceGenerator().moveUniqueConstraint(targetIndex, sourceIndex); + this.fireItemMoved(UNIQUE_CONSTRAINTS_LIST, targetIndex, sourceIndex); + } + + protected void addUniqueConstraint(int index, JavaUniqueConstraint uniqueConstraint) { + this.addItemToList(index, uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + protected void addUniqueConstraint(JavaUniqueConstraint uniqueConstraint) { + this.addUniqueConstraint(this.uniqueConstraints.size(), uniqueConstraint); + } + + protected void removeUniqueConstraint_(JavaUniqueConstraint uniqueConstraint) { + this.removeItemFromList(uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + + //******************* UniqueConstraint.Owner implementation ****************** + + public Iterator<String> candidateUniqueConstraintColumnNames() { + org.eclipse.jpt.db.Table dbTable = this.getDbTable(); + return (dbTable != null) ? dbTable.getSortedColumnIdentifiers().iterator() : EmptyIterator.<String>instance(); + } + + + // ********** resource => context ********** + + public void initialize(TableGeneratorAnnotation tableGeneratorAnnotation) { + super.initialize(tableGeneratorAnnotation); + this.specifiedTable = tableGeneratorAnnotation.getTable(); + this.defaultSchema = this.buildDefaultSchema(); + this.specifiedSchema = tableGeneratorAnnotation.getSchema(); + this.defaultCatalog = this.buildDefaultCatalog(); + this.specifiedCatalog = tableGeneratorAnnotation.getCatalog(); + this.specifiedPkColumnName = tableGeneratorAnnotation.getPkColumnName(); + this.specifiedValueColumnName = tableGeneratorAnnotation.getValueColumnName(); + this.specifiedPkColumnValue = tableGeneratorAnnotation.getPkColumnValue(); + this.initializeUniqueConstraints(tableGeneratorAnnotation); + } + + protected void initializeUniqueConstraints(TableGeneratorAnnotation tableGeneratorAnnotation) { + for (Iterator<UniqueConstraintAnnotation> stream = tableGeneratorAnnotation.uniqueConstraints(); stream.hasNext(); ) { + this.uniqueConstraints.add(this.buildUniqueConstraint(stream.next())); + } + } + + public void update(TableGeneratorAnnotation tableGeneratorAnnotation) { + super.update(tableGeneratorAnnotation); + this.setSpecifiedTable_(tableGeneratorAnnotation.getTable()); + this.setDefaultSchema(this.buildDefaultSchema()); + this.setSpecifiedSchema_(tableGeneratorAnnotation.getSchema()); + this.setDefaultCatalog(this.buildDefaultCatalog()); + this.setSpecifiedCatalog_(tableGeneratorAnnotation.getCatalog()); + this.setSpecifiedPkColumnName_(tableGeneratorAnnotation.getPkColumnName()); + this.setSpecifiedValueColumnName_(tableGeneratorAnnotation.getValueColumnName()); + this.setSpecifiedPkColumnValue_(tableGeneratorAnnotation.getPkColumnValue()); + this.updateUniqueConstraints(tableGeneratorAnnotation); + } + + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + protected void updateUniqueConstraints(TableGeneratorAnnotation tableGeneratorAnnotation) { + ListIterator<JavaUniqueConstraint> contextConstraints = this.uniqueConstraints(); + ListIterator<UniqueConstraintAnnotation> resourceConstraints = tableGeneratorAnnotation.uniqueConstraints(); + + while (contextConstraints.hasNext()) { + JavaUniqueConstraint uniqueConstraint = contextConstraints.next(); + if (resourceConstraints.hasNext()) { + uniqueConstraint.update(resourceConstraints.next()); + } + else { + removeUniqueConstraint_(uniqueConstraint); + } + } + + while (resourceConstraints.hasNext()) { + addUniqueConstraint(buildUniqueConstraint(resourceConstraints.next())); + } + } + + protected JavaUniqueConstraint buildUniqueConstraint(UniqueConstraintAnnotation uniqueConstraintAnnotation) { + JavaUniqueConstraint uniqueConstraint = getJpaFactory().buildJavaUniqueConstraint(this, this); + uniqueConstraint.initialize(uniqueConstraintAnnotation); + return uniqueConstraint; + } + + + // ********** database stuff ********** + + public Table getDbTable() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getTable()); + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaUniqueConstraint constraint : CollectionTools.iterable(this.uniqueConstraints())) { + result = constraint.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + /** + * called if the database is connected: + * table, schema, catalog, pkColumnName, valueColumnName + */ + @Override + public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.tableTouches(pos, astRoot)) { + return this.getJavaCandidateTables(filter).iterator(); + } + if (this.schemaTouches(pos, astRoot)) { + return this.getJavaCandidateSchemata(filter).iterator(); + } + if (this.catalogTouches(pos, astRoot)) { + return this.getJavaCandidateCatalogs(filter).iterator(); + } + if (this.pkColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateColumnNames(filter).iterator(); + } + if (this.valueColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateColumnNames(filter).iterator(); + } + return null; + } + + // ********** code assist: table + + protected boolean tableTouches(int pos, CompilationUnit astRoot) { + return this.getResourceGenerator().tableTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateTables(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateTables(filter)); + } + + protected Iterable<String> getCandidateTables(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateTables(), filter); + } + + protected Iterable<String> getCandidateTables() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema != null) ? dbSchema.getSortedTableIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: schema + + protected boolean schemaTouches(int pos, CompilationUnit astRoot) { + return this.getResourceGenerator().schemaTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateSchemata(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateSchemata(filter)); + } + + protected Iterable<String> getCandidateSchemata(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateSchemata(), filter); + } + + protected Iterable<String> getCandidateSchemata() { + SchemaContainer schemaContainer = this.getDbSchemaContainer(); + return (schemaContainer != null) ? schemaContainer.getSortedSchemaIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: catalog + + protected boolean catalogTouches(int pos, CompilationUnit astRoot) { + return this.getResourceGenerator().catalogTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateCatalogs(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateCatalogs(filter)); + } + + protected Iterable<String> getCandidateCatalogs(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateCatalogs(), filter); + } + + protected Iterable<String> getCandidateCatalogs() { + Database db = this.getDatabase(); + return (db != null) ? db.getSortedCatalogIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: pkColumnName + + protected boolean pkColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.getResourceGenerator().pkColumnNameTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateColumnNames(filter)); + } + + protected Iterable<String> getCandidateColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateColumnNames(), filter); + } + + protected Iterable<String> getCandidateColumnNames() { + Table table = this.getDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: valueColumnName + + protected boolean valueColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.getResourceGenerator().valueColumnNameTouches(pos, astRoot); + } + + + // ********** misc ********** + + @Override + protected TableGeneratorAnnotation getResourceGenerator() { + return (TableGeneratorAnnotation) super.getResourceGenerator(); + } + + public int getDefaultInitialValue() { + return DEFAULT_INITIAL_VALUE; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java new file mode 100644 index 0000000000..10e125fbab --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.TemporalType; +import org.eclipse.jpt.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.core.context.java.JavaTemporalConverter; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.resource.java.TemporalAnnotation; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericJavaTemporalConverter extends AbstractJavaJpaContextNode + implements JavaTemporalConverter +{ + protected TemporalType temporalType; + + protected JavaResourcePersistentAttribute resourcePersistentAttribute; + + public GenericJavaTemporalConverter(JavaAttributeMapping parent, JavaResourcePersistentAttribute jrpa) { + super(parent); + this.initialize(jrpa); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.TEMPORAL_CONVERTER; + } + + protected String getAnnotationName() { + return TemporalAnnotation.ANNOTATION_NAME; + } + + public void addToResourceModel() { + this.resourcePersistentAttribute.addAnnotation(getAnnotationName()); + } + + public void removeFromResourceModel() { + this.resourcePersistentAttribute.removeAnnotation(getAnnotationName()); + } + + public TemporalType getTemporalType() { + return this.temporalType; + } + + public void setTemporalType(TemporalType newTemporalType) { + TemporalType oldTemporalType = this.temporalType; + this.temporalType = newTemporalType; + this.getResourceTemporal().setValue(TemporalType.toJavaResourceModel(newTemporalType)); + firePropertyChanged(TEMPORAL_TYPE_PROPERTY, oldTemporalType, newTemporalType); + } + + protected void setTemporalType_(TemporalType newTemporalType) { + TemporalType oldTemporalType = this.temporalType; + this.temporalType = newTemporalType; + firePropertyChanged(TEMPORAL_TYPE_PROPERTY, oldTemporalType, newTemporalType); + } + + + protected TemporalAnnotation getResourceTemporal() { + return (TemporalAnnotation) this.resourcePersistentAttribute. + getAnnotation(getAnnotationName()); + } + + protected void initialize(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistentAttribute = jrpa; + this.temporalType = this.temporalType(getResourceTemporal()); + } + + public void update(JavaResourcePersistentAttribute jrpa) { + this.resourcePersistentAttribute = jrpa; + this.setTemporalType_(this.temporalType(getResourceTemporal())); + } + + protected TemporalType temporalType(TemporalAnnotation resourceTemporal) { + return resourceTemporal == null ? null : TemporalType.fromJavaResourceModel(resourceTemporal.getValue()); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.getResourceTemporal().getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTransientMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTransientMapping.java new file mode 100644 index 0000000000..53f7a781d1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaTransientMapping.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.List; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.context.java.JavaTransientMapping; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaAttributeMapping; +import org.eclipse.jpt.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.core.resource.java.TransientAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericJavaTransientMapping + extends AbstractJavaAttributeMapping<TransientAnnotation> + implements JavaTransientMapping +{ + public GenericJavaTransientMapping(JavaPersistentAttribute parent) { + super(parent); + } + + public String getKey() { + return MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY; + } + + public String getAnnotationName() { + return TransientAnnotation.ANNOTATION_NAME; + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + } + + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java new file mode 100644 index 0000000000..a24d8e8e73 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.UniqueConstraint; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.context.java.JavaUniqueConstraint; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.UniqueConstraintAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.Filter; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; + +public class GenericJavaUniqueConstraint extends AbstractJavaJpaContextNode + implements JavaUniqueConstraint +{ + + protected final List<String> columnNames; + + protected UniqueConstraintAnnotation resourceUniqueConstraint; + + protected Owner owner; + public GenericJavaUniqueConstraint(JavaJpaContextNode parent, Owner owner) { + super(parent); + this.owner = owner; + this.columnNames = new ArrayList<String>(); + } + + public Owner getOwner() { + return this.owner; + } + + public ListIterator<String> columnNames() { + return new CloneListIterator<String>(this.columnNames); + } + + public int columnNamesSize() { + return this.columnNames.size(); + } + + public void addColumnName(int index, String columnName) { + this.columnNames.add(index, columnName); + this.resourceUniqueConstraint.addColumnName(index, columnName); + fireItemAdded(UniqueConstraint.COLUMN_NAMES_LIST, index, columnName); + } + + protected void addColumnName_(int index, String columnName) { + this.columnNames.add(index, columnName); + fireItemAdded(UniqueConstraint.COLUMN_NAMES_LIST, index, columnName); + } + + public void removeColumnName(String columnName) { + this.removeColumnName(this.columnNames.indexOf(columnName)); + } + + public void removeColumnName(int index) { + String removedColumnName = this.columnNames.remove(index); + this.resourceUniqueConstraint.removeColumnName(index); + fireItemRemoved(UniqueConstraint.COLUMN_NAMES_LIST, index, removedColumnName); + } + + protected void removeColumnName_(int index) { + String removedColumnName = this.columnNames.remove(index); + fireItemRemoved(UniqueConstraint.COLUMN_NAMES_LIST, index, removedColumnName); + } + + public void moveColumnName(int targetIndex, int sourceIndex) { + CollectionTools.move(this.columnNames, targetIndex, sourceIndex); + this.resourceUniqueConstraint.moveColumnName(targetIndex, sourceIndex); + fireItemMoved(UniqueConstraint.COLUMN_NAMES_LIST, targetIndex, sourceIndex); + } + + public void initialize(UniqueConstraintAnnotation uca) { + this.resourceUniqueConstraint = uca; + this.initializeColumnNames(uca); + } + + protected void initializeColumnNames(UniqueConstraintAnnotation uca) { + ListIterator<String> annotationColumnNames = uca.columnNames(); + + for (String resourceColumnName : CollectionTools.iterable(annotationColumnNames)) { + this.columnNames.add(resourceColumnName); + } + } + + public void update(UniqueConstraintAnnotation uca) { + this.resourceUniqueConstraint = uca; + this.updateColumnNames(uca); + } + + protected void updateColumnNames(UniqueConstraintAnnotation uca) { + ListIterator<String> annotationColumnNames = uca.columnNames(); + + int index = 0; + for (String resourceColumnName : CollectionTools.iterable(annotationColumnNames)) { + if (columnNamesSize() > index) { + if (this.columnNames.get(index) != resourceColumnName) { + addColumnName_(index, resourceColumnName); + } + } + else { + addColumnName_(index, resourceColumnName); + } + index++; + } + + for ( ; index < columnNamesSize(); ) { + removeColumnName_(index); + } + } + + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.resourceUniqueConstraint.getTextRange(astRoot); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.columnNames); + } + + + // ********** code-assist ********** + + @Override + public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.columnNamesTouches(pos, astRoot)) { + return this.javaCandidateColumnNames(filter); + } + return null; + } + + private boolean columnNamesTouches(int pos, CompilationUnit astRoot) { + return this.resourceUniqueConstraint.columnNamesTouches(pos, astRoot); + } + + private Iterator<String> javaCandidateColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.candidateColumnNames(filter)); + } + + private Iterator<String> candidateColumnNames(Filter<String> filter) { + return new FilteringIterator<String>(this.candidateColumnNames(), filter); + } + + private Iterator<String> candidateColumnNames() { + return this.getOwner().candidateUniqueConstraintColumnNames(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaVersionMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaVersionMapping.java new file mode 100644 index 0000000000..2c989ab68a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/GenericJavaVersionMapping.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaVersionMapping; + + +public class GenericJavaVersionMapping + extends AbstractJavaVersionMapping +{ + + public GenericJavaVersionMapping(JavaPersistentAttribute parent) { + super(parent); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaAssociationOverrideContainer.java new file mode 100644 index 0000000000..faf6749089 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaAssociationOverrideContainer.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.java.JavaAssociationOverride; +import org.eclipse.jpt.core.context.java.JavaAssociationOverrideContainer; +import org.eclipse.jpt.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; + +public class NullJavaAssociationOverrideContainer extends AbstractJavaJpaContextNode + implements JavaAssociationOverrideContainer +{ + public NullJavaAssociationOverrideContainer(JavaJpaContextNode parent) { + super(parent); + } + + public void initialize(JavaResourcePersistentMember jrpm) { + // no-op + } + + public void update(JavaResourcePersistentMember jrpm) { + // no-op + } + + public JavaAssociationOverride getAssociationOverrideNamed(String name) { + return null; + } + + public ListIterator<JavaAssociationOverride> associationOverrides() { + return EmptyListIterator.instance(); + } + + public int associationOverridesSize() { + return 0; + } + + public ListIterator<JavaAssociationOverride> virtualAssociationOverrides() { + return EmptyListIterator.instance(); + } + + public int virtualAssociationOverridesSize() { + return 0; + } + + public ListIterator<JavaAssociationOverride> specifiedAssociationOverrides() { + return EmptyListIterator.instance(); + } + + public int specifiedAssociationOverridesSize() { + return 0; + } + + public void moveSpecifiedAssociationOverride(int targetIndex, int sourceIndex) { + throw new UnsupportedOperationException(); + } + + + //********** Validation ******************************************** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinColumnJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinColumnJoiningStrategy.java new file mode 100644 index 0000000000..44ebd876a7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinColumnJoiningStrategy.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.JoinColumnEnabledRelationshipReference; +import org.eclipse.jpt.core.context.JoinColumnJoiningStrategy; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.core.context.java.JavaJoinColumnJoiningStrategy; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; + +public class NullJavaJoinColumnJoiningStrategy + extends AbstractJavaJpaContextNode + implements JavaJoinColumnJoiningStrategy +{ + + protected NullJavaJoinColumnJoiningStrategy(JoinColumnEnabledRelationshipReference parent) { + super(parent); + } + + public void initializeFrom(JoinColumnJoiningStrategy oldStrategy) { + throw new UnsupportedOperationException(); + } + + @Override + public JoinColumnEnabledRelationshipReference getParent() { + return (JoinColumnEnabledRelationshipReference) super.getParent(); + } + + public JoinColumnEnabledRelationshipReference getRelationshipReference() { + return this.getParent(); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getRelationshipReference().getRelationshipMapping(); + } + + public void addStrategy() { + throw new UnsupportedOperationException(); + } + + public void removeStrategy() { + //do nothing, no join column to remove + } + + public boolean isTargetForeignKeyRelationship() { + return false; + } + + public TypeMapping getRelationshipTarget() { + return null; + } + + // **************** join columns ******************************************* + + public ListIterator<JavaJoinColumn> joinColumns() { + throw new UnsupportedOperationException(); + + } + + public int joinColumnsSize() { + throw new UnsupportedOperationException(); + } + + + // **************** default join column ************************************ + + public JavaJoinColumn getDefaultJoinColumn() { + throw new UnsupportedOperationException(); + } + + // **************** specified join columns ********************************* + + public ListIterator<JavaJoinColumn> specifiedJoinColumns() { + throw new UnsupportedOperationException(); + } + + public int specifiedJoinColumnsSize() { + throw new UnsupportedOperationException(); + } + + public boolean hasSpecifiedJoinColumns() { + return false; + } + + public JavaJoinColumn addSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + throw new UnsupportedOperationException(); + } + + + // **************** resource => context ************************************ + + public void initialize() { + //no-op + } + + + public void update() { + //no-op + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + throw new UnsupportedOperationException(); + } + + public String getColumnTableNotValidDescription() { + throw new UnsupportedOperationException(); + } + + public Table getDbTable(String tableName) { + throw new UnsupportedOperationException(); + } + + public Table getReferencedColumnDbTable() { + throw new UnsupportedOperationException(); + } + + public String getTableName() { + return null; + } + + public boolean isOverridableAssociation() { + return false; + } + + public boolean tableNameIsInvalid(String tableName) { + throw new UnsupportedOperationException(); + } + + public TypeMapping getRelationshipSource() { + return getRelationshipMapping().getTypeMapping(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinTableJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinTableJoiningStrategy.java new file mode 100644 index 0000000000..47bb72157d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/NullJavaJoinTableJoiningStrategy.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.core.context.JoinTableEnabledRelationshipReference; +import org.eclipse.jpt.core.context.JoinTableJoiningStrategy; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaJoinTable; +import org.eclipse.jpt.core.context.java.JavaJoinTableJoiningStrategy; +import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.core.resource.java.JoinTableAnnotation; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; + +public class NullJavaJoinTableJoiningStrategy + extends AbstractJavaJpaContextNode + implements JavaJoinTableJoiningStrategy +{ + + public NullJavaJoinTableJoiningStrategy(JoinTableEnabledRelationshipReference parent) { + super(parent); + } + + public void initializeFrom(JoinTableJoiningStrategy oldStrategy) { + throw new UnsupportedOperationException(); + } + + @Override + public JoinTableEnabledRelationshipReference getParent() { + return (JoinTableEnabledRelationshipReference) super.getParent(); + } + + public JoinTableEnabledRelationshipReference getRelationshipReference() { + return this.getParent(); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getRelationshipReference().getRelationshipMapping(); + } + + public void addStrategy() { + //do nothing + } + + public void removeStrategy() { + //do nothing, no join table to remove + } + + + + // **************** resource => context ************************************ + + public void initialize() { + //no-op + } + + + public void update() { + //no-op + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + throw new UnsupportedOperationException(); + } + + public String getColumnTableNotValidDescription() { + throw new UnsupportedOperationException(); + } + + public Table getDbTable(String tableName) { + throw new UnsupportedOperationException(); + } + + public String getTableName() { + return null; + } + + public boolean isOverridableAssociation() { + return false; + } + + public boolean tableNameIsInvalid(String tableName) { + throw new UnsupportedOperationException(); + } + + public TypeMapping getTypeMapping() { + return getRelationshipMapping().getTypeMapping(); + } + + public JoinTableAnnotation getAnnotation() { + return null; + } + + public JavaJoinTable getJoinTable() { + return null; + } + + public String getJoinTableDefaultName() { + return null; + } + + public boolean shouldValidateAgainstDatabase() { + return false; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/VirtualAssociationOverride1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/VirtualAssociationOverride1_0Annotation.java new file mode 100644 index 0000000000..2738d5cfb1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/java/VirtualAssociationOverride1_0Annotation.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.java; + +import org.eclipse.jpt.core.context.JoiningStrategy; +import org.eclipse.jpt.core.internal.context.java.VirtualAssociationOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember; + +/** + * javax.persistence.AssociationOverride + */ +public class VirtualAssociationOverride1_0Annotation + extends VirtualAssociationOverrideAnnotation +{ + + public VirtualAssociationOverride1_0Annotation(JavaResourcePersistentMember parent, String name, JoiningStrategy joiningStrategy) { + super(parent, name, joiningStrategy); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/AbstractOrmOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/AbstractOrmOverride.java new file mode 100644 index 0000000000..b735003d5e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/AbstractOrmOverride.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlOverride; +import org.eclipse.jpt.core.utility.TextRange; + + +public class AbstractOrmOverride extends AbstractOrmXmlContextNode +{ + + protected String name; + + protected final BaseOverride.Owner owner; + + protected XmlOverride resourceOverride; + + public AbstractOrmOverride(XmlContextNode parent, BaseOverride.Owner owner, XmlOverride resourceOverride) { + super(parent); + this.owner = owner; + this.resourceOverride = resourceOverride; + this.name = getResourceName(); + } + + @Override + public XmlContextNode getParent() { + return (XmlContextNode) super.getParent(); + } + + public BaseOverride.Owner getOwner() { + return this.owner; + } + + protected XmlOverride getResourceOverride() { + return this.resourceOverride; + } + + protected void update(XmlOverride resourceOverride) { + this.resourceOverride = resourceOverride; + this.setName_(this.getResourceName()); + } + + + // ********************* name **************** + + public String getName() { + return this.name; + } + + public void setName(String newName) { + String oldName = this.name; + this.name = newName; + this.resourceOverride.setName(newName); + firePropertyChanged(BaseOverride.NAME_PROPERTY, oldName, newName); + } + + protected void setName_(String newName) { + String oldName = this.name; + this.name = newName; + firePropertyChanged(BaseOverride.NAME_PROPERTY, oldName, newName); + } + + protected String getResourceName() { + return this.resourceOverride.getName(); + } + + public TextRange getValidationTextRange() { + TextRange textRange = this.resourceOverride.getValidationTextRange(); + return textRange == null ? getParent().getValidationTextRange() : textRange; + } + + + //****************** miscellaneous ******************** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericEntityMappings.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericEntityMappings.java new file mode 100644 index 0000000000..43ba8c6637 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericEntityMappings.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.orm.OrmXml; +import org.eclipse.jpt.core.internal.context.orm.AbstractEntityMappings; +import org.eclipse.jpt.core.resource.orm.XmlEntityMappings; + +/** + * <code>orm.xml</code> file + * <br> + * <code>entity-mappings</code> element + */ +public class GenericEntityMappings + extends AbstractEntityMappings +{ + public GenericEntityMappings(OrmXml parent, XmlEntityMappings resource) { + super(parent, resource); + } + + @Override + protected String latestDocumentVersion() { + return this.getJpaPlatform().getMostRecentSupportedResourceType(JptCorePlugin.ORM_XML_CONTENT_TYPE).getVersion(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java new file mode 100644 index 0000000000..df01a97628 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideRelationshipReference; +import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmAssociationOverride extends AbstractOrmOverride + implements OrmAssociationOverride +{ + protected final OrmAssociationOverrideRelationshipReference relationshipReference; + + + public GenericOrmAssociationOverride(OrmAssociationOverrideContainer parent, AssociationOverride.Owner owner, XmlAssociationOverride xmlAssociationOverride) { + super(parent, owner, xmlAssociationOverride); + this.relationshipReference = this.buildRelationshipReference(); + } + + @Override + public OrmAssociationOverrideContainer getParent() { + return (OrmAssociationOverrideContainer) super.getParent(); + } + + @Override + public Owner getOwner() { + return (Owner) super.getOwner(); + } + + protected OrmAssociationOverrideRelationshipReference buildRelationshipReference() { + return getXmlContextNodeFactory().buildOrmAssociationOverrideRelationshipReference(this, getResourceOverride()); + } + + public void initializeFrom(AssociationOverride oldAssociationOverride) { + this.setName(oldAssociationOverride.getName()); + this.relationshipReference.initializeFrom(oldAssociationOverride.getRelationshipReference()); + } + + public void update(XmlAssociationOverride xao) { + super.update(xao); + this.relationshipReference.update(xao); + } + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + public OrmAssociationOverride setVirtual(boolean virtual) { + return (OrmAssociationOverride) getOwner().setVirtual(virtual, this); + } + + @Override + protected XmlAssociationOverride getResourceOverride() { + return (XmlAssociationOverride) super.getResourceOverride(); + } + + public OrmAssociationOverrideRelationshipReference getRelationshipReference() { + return this.relationshipReference; + } + + + // ********** OrmAssociationOverride implementation ********** + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.relationshipReference.validate(messages, reporter); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java new file mode 100644 index 0000000000..c0e87d796a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java @@ -0,0 +1,380 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.emf.common.util.EList; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.JoiningStrategy; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.RelationshipReference; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmAssociationOverrideContainer extends AbstractOrmXmlContextNode + implements OrmAssociationOverrideContainer +{ + + protected final List<OrmAssociationOverride> specifiedAssociationOverrides; + + protected final List<OrmAssociationOverride> virtualAssociationOverrides; + + protected final OrmAssociationOverrideContainer.Owner owner; + + public GenericOrmAssociationOverrideContainer(XmlContextNode parent, OrmAssociationOverrideContainer.Owner owner) { + super(parent); + this.owner = owner; + this.specifiedAssociationOverrides = new ArrayList<OrmAssociationOverride>(); + this.virtualAssociationOverrides = new ArrayList<OrmAssociationOverride>(); + this.initializeSpecifiedAssociationOverrides(); + this.initializeVirtualAssociationOverrides(); + } + + protected Owner getOwner() { + return this.owner; + } + + protected EList<XmlAssociationOverride> getResourceAssociationOverrides() { + return getOwner().getResourceAssociationOverrides(); + } + + @SuppressWarnings("unchecked") + public ListIterator<OrmAssociationOverride> associationOverrides() { + return new CompositeListIterator<OrmAssociationOverride>(specifiedAssociationOverrides(), virtualAssociationOverrides()); + } + + public int associationOverridesSize() { + return this.specifiedAssociationOverridesSize() + this.virtualAssociationOverridesSize(); + } + + public ListIterator<OrmAssociationOverride> virtualAssociationOverrides() { + return new CloneListIterator<OrmAssociationOverride>(this.virtualAssociationOverrides); + } + + public int virtualAssociationOverridesSize() { + return this.virtualAssociationOverrides.size(); + } + + protected void addVirtualAssociationOverride(OrmAssociationOverride associationOverride) { + addItemToList(associationOverride, this.virtualAssociationOverrides, VIRTUAL_ASSOCIATION_OVERRIDES_LIST); + } + + protected void removeVirtualAssociationOverride(OrmAssociationOverride associationOverride) { + removeItemFromList(associationOverride, this.virtualAssociationOverrides, VIRTUAL_ASSOCIATION_OVERRIDES_LIST); + } + + protected OrmAssociationOverride setAssociationOverrideVirtual(boolean virtual, OrmAssociationOverride associationOverride) { + if (virtual) { + return setAssociationOverrideVirtual(associationOverride); + } + return setAssociationOverrideSpecified(associationOverride); + } + + protected OrmAssociationOverride setAssociationOverrideVirtual(OrmAssociationOverride associationOverride) { + int index = this.specifiedAssociationOverrides.indexOf(associationOverride); + this.specifiedAssociationOverrides.remove(index); + String associationOverrideName = associationOverride.getName(); + //add the virtual attribute override so that I can control the order that change notification is sent. + //otherwise when we remove the annotation from java we will get an update and add the attribute override + //during the udpate. This causes the UI to be flaky, since change notification might not occur in the correct order + OrmAssociationOverride virtualAssociationOverride = null; + if (associationOverrideName != null) { + for (String name : CollectionTools.iterable(allOverridableAssociationNames())) { + if (name.equals(associationOverrideName)) { + //store the virtualAssociationOverride so we can fire change notification later + virtualAssociationOverride = buildVirtualAssociationOverride(name); + this.virtualAssociationOverrides.add(virtualAssociationOverride); + } + } + } + + this.getResourceAssociationOverrides().remove(index); + fireItemRemoved(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, index, associationOverride); + + if (virtualAssociationOverride != null) { + fireItemAdded(VIRTUAL_ASSOCIATION_OVERRIDES_LIST, virtualAssociationOverridesSize() - 1, virtualAssociationOverride); + } + return virtualAssociationOverride; + } + + protected OrmAssociationOverride setAssociationOverrideSpecified(OrmAssociationOverride oldAssociationOverride) { + int index = specifiedAssociationOverridesSize(); + XmlAssociationOverride xmlAssociationOverride = buildResourceAssociationOverride(); + OrmAssociationOverride newAssociationOverride = buildAssociationOverride(xmlAssociationOverride); + this.specifiedAssociationOverrides.add(index, newAssociationOverride); + + this.getResourceAssociationOverrides().add(xmlAssociationOverride); + + int defaultIndex = this.virtualAssociationOverrides.indexOf(oldAssociationOverride); + this.virtualAssociationOverrides.remove(defaultIndex); + + newAssociationOverride.initializeFrom(oldAssociationOverride); + + this.fireItemRemoved(VIRTUAL_ASSOCIATION_OVERRIDES_LIST, defaultIndex, oldAssociationOverride); + this.fireItemAdded(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, index, newAssociationOverride); + + return newAssociationOverride; + } + + public ListIterator<OrmAssociationOverride> specifiedAssociationOverrides() { + return new CloneListIterator<OrmAssociationOverride>(this.specifiedAssociationOverrides); + } + + public int specifiedAssociationOverridesSize() { + return this.specifiedAssociationOverrides.size(); + } + + protected void addSpecifiedAssociationOverride(int index, OrmAssociationOverride associationOverride) { + addItemToList(index, associationOverride, this.specifiedAssociationOverrides, SPECIFIED_ASSOCIATION_OVERRIDES_LIST); + } + + protected void addSpecifiedAssociationOverride(OrmAssociationOverride associationOverride) { + this.addSpecifiedAssociationOverride(this.specifiedAssociationOverrides.size(), associationOverride); + } + + protected void removeSpecifiedAssociationOverride_(OrmAssociationOverride associationOverride) { + removeItemFromList(associationOverride, this.specifiedAssociationOverrides, SPECIFIED_ASSOCIATION_OVERRIDES_LIST); + } + + public void moveSpecifiedAssociationOverride(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedAssociationOverrides, targetIndex, sourceIndex); + this.getResourceAssociationOverrides().move(targetIndex, sourceIndex); + fireItemMoved(SPECIFIED_ASSOCIATION_OVERRIDES_LIST, targetIndex, sourceIndex); + } + + public OrmAssociationOverride getAssociationOverrideNamed(String name) { + return (OrmAssociationOverride) getOverrideNamed(name, associationOverrides()); + } + + public boolean containsAssociationOverride(String name) { + return containsOverride(name, associationOverrides()); + } + + public boolean containsSpecifiedAssociationOverride(String name) { + return containsOverride(name, specifiedAssociationOverrides()); + } + + public boolean containsDefaultAssociationOverride(String name) { + return containsOverride(name, virtualAssociationOverrides()); + } + + private BaseOverride getOverrideNamed(String name, ListIterator<? extends BaseOverride> overrides) { + for (BaseOverride override : CollectionTools.iterable(overrides)) { + String overrideName = override.getName(); + if (overrideName == null && name == null) { + return override; + } + if (overrideName != null && overrideName.equals(name)) { + return override; + } + } + return null; + } + + private boolean containsOverride(String name, ListIterator<? extends BaseOverride> overrides) { + return getOverrideNamed(name, overrides) != null; + } + + protected Iterator<String> allOverridableAssociationNames() { + return getOwner().allOverridableNames(); + } + + protected void initializeVirtualAssociationOverrides() { + for (String name : CollectionTools.iterable(allOverridableAssociationNames())) { + OrmAssociationOverride ormAssociationOverride = getAssociationOverrideNamed(name); + if (ormAssociationOverride == null) { + this.virtualAssociationOverrides.add(buildVirtualAssociationOverride(name)); + } + } + } + + protected OrmAssociationOverride buildVirtualAssociationOverride(String name) { + return buildAssociationOverride(buildVirtualXmlAssociationOverride(name)); + } + + protected XmlAssociationOverride buildVirtualXmlAssociationOverride(String name) { + RelationshipReference relationshipReference = this.resolveAssociationOverrideRelationshipReference(name); + return buildVirtualXmlAssociationOverride(name, relationshipReference.getPredominantJoiningStrategy()); + } + + protected XmlAssociationOverride buildVirtualXmlAssociationOverride(String name, JoiningStrategy joiningStrategy) { + return getXmlContextNodeFactory().buildVirtualXmlAssociationOverride(name, getOwner().getTypeMapping(), joiningStrategy); + } + + private RelationshipReference resolveAssociationOverrideRelationshipReference(String associationOverrideName) { + return getOwner().resolveRelationshipReference(associationOverrideName); + } + + + protected void initializeSpecifiedAssociationOverrides() { + for (XmlAssociationOverride associationOverride : this.getResourceAssociationOverrides()) { + this.specifiedAssociationOverrides.add(buildAssociationOverride(associationOverride)); + } + } + + public void update() { + this.updateSpecifiedAssociationOverrides(); + this.updateVirtualAssociationOverrides(); + } + + protected void updateSpecifiedAssociationOverrides() { + // make a copy of the XML overrides (to prevent ConcurrentModificationException) + Iterator<XmlAssociationOverride> xmlOverrides = new CloneIterator<XmlAssociationOverride>(this.getResourceAssociationOverrides()); + + for (Iterator<OrmAssociationOverride> contextOverrides = this.specifiedAssociationOverrides(); contextOverrides.hasNext(); ) { + OrmAssociationOverride contextOverride = contextOverrides.next(); + if (xmlOverrides.hasNext()) { + contextOverride.update(xmlOverrides.next()); + } + else { + removeSpecifiedAssociationOverride_(contextOverride); + } + } + + while (xmlOverrides.hasNext()) { + addSpecifiedAssociationOverride(buildAssociationOverride(xmlOverrides.next())); + } + } + + protected void updateVirtualAssociationOverrides() { + Iterator<String> overridableAssociations = allOverridableAssociationNames(); + ListIterator<OrmAssociationOverride> virtualAssociationOverridesCopy = virtualAssociationOverrides(); + + for (String name : CollectionTools.iterable(overridableAssociations)) { + OrmAssociationOverride ormAssociationOverride = getAssociationOverrideNamed(name); + if (ormAssociationOverride != null && !ormAssociationOverride.isVirtual()) { + continue; + } + if (ormAssociationOverride != null) { + if (virtualAssociationOverridesCopy.hasNext()) { + OrmAssociationOverride virtualAssociationOverride = virtualAssociationOverridesCopy.next(); + virtualAssociationOverride.update(buildVirtualXmlAssociationOverride(name)); + } + else { + addVirtualAssociationOverride(buildVirtualAssociationOverride(name)); + } + } + else { + addVirtualAssociationOverride(buildVirtualAssociationOverride(name)); + } + } + for (OrmAssociationOverride virtualAssociationOverride : CollectionTools.iterable(virtualAssociationOverridesCopy)) { + removeVirtualAssociationOverride(virtualAssociationOverride); + } + } + + protected OrmAssociationOverride buildAssociationOverride(XmlAssociationOverride associationOverride) { + return getXmlContextNodeFactory().buildOrmAssociationOverride(this, buildAssociationOverrideOwner(), associationOverride); + } + + protected XmlAssociationOverride buildResourceAssociationOverride() { + return OrmFactory.eINSTANCE.createXmlAssociationOverride(); + } + + protected AssociationOverride.Owner buildAssociationOverrideOwner() { + return new AssociationOverrideOwner(); + } + + //************ validation *************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + for (Iterator<OrmAssociationOverride> stream = this.associationOverrides(); stream.hasNext(); ) { + stream.next().validate(messages, reporter); + } + } + + public TextRange getValidationTextRange() { + return getOwner().getValidationTextRange(); + } + + + protected class AssociationOverrideOwner implements AssociationOverride.Owner { + + public RelationshipMapping getRelationshipMapping(String attributeName) { + return MappingTools.getRelationshipMapping(attributeName, getOwner().getOverridableTypeMapping()); + } + + public boolean isVirtual(BaseOverride override) { + return GenericOrmAssociationOverrideContainer.this.virtualAssociationOverrides.contains(override); + } + + public BaseOverride setVirtual(boolean virtual, BaseOverride override) { + return GenericOrmAssociationOverrideContainer.this.setAssociationOverrideVirtual(virtual, (OrmAssociationOverride) override); + } + + public TypeMapping getTypeMapping() { + return getOwner().getTypeMapping(); + } + + public Iterator<String> allOverridableAttributeNames() { + return GenericOrmAssociationOverrideContainer.this.allOverridableAssociationNames(); + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + public String getDefaultTableName() { + return getOwner().getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedReferencedColumnNameMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedReferencedColumnNameMessage(override, column, textRange); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(override, column, textRange); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(override, column, textRange); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideRelationshipReference.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideRelationshipReference.java new file mode 100644 index 0000000000..32e785991e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideRelationshipReference.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.JoiningStrategy; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAssociationOverrideRelationshipReference; +import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride; + +public class GenericOrmAssociationOverrideRelationshipReference extends AbstractOrmAssociationOverrideRelationshipReference +{ + + public GenericOrmAssociationOverrideRelationshipReference(OrmAssociationOverride parent, XmlAssociationOverride xao) { + super(parent, xao); + } + + @Override + protected JoiningStrategy calculatePredominantJoiningStrategy() { + return this.joinColumnJoiningStrategy; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java new file mode 100644 index 0000000000..267264314b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java @@ -0,0 +1,241 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.AttributeOverride; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmAttributeOverride; +import org.eclipse.jpt.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.core.context.orm.OrmColumn; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.AttributeOverride2_0; +import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlAttributeOverride; +import org.eclipse.jpt.core.resource.orm.XmlColumn; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmAttributeOverride + extends AbstractOrmOverride + implements AttributeOverride2_0, OrmAttributeOverride, OrmColumn.Owner +{ + protected final OrmColumn column; + + /* 2.0 feature - a relationship may map this attribute override */ + protected boolean mappedByRelationship; + + + public GenericOrmAttributeOverride( + OrmAttributeOverrideContainer parent, + AttributeOverride.Owner owner, + XmlAttributeOverride resourceAttributeOverride) { + + super(parent, owner, resourceAttributeOverride); + this.column = getXmlContextNodeFactory().buildOrmColumn(this, this); + this.column.initialize(resourceAttributeOverride.getColumn()); + + this.mappedByRelationship = //calculateMappedByRelationship(); + // TODO - move this real calculation to a (currently nonexistent) initialize method + false; + } + + + public OrmAttributeOverride setVirtual(boolean virtual) { + return (OrmAttributeOverride) getOwner().setVirtual(virtual, this); + } + + @Override + public Owner getOwner() { + return (Owner) super.getOwner(); + } + + @Override + protected XmlAttributeOverride getResourceOverride() { + return (XmlAttributeOverride) super.getResourceOverride(); + } + + + // ********************* column **************** + + public OrmColumn getColumn() { + return this.column; + } + + //************* NamedColumn.Owner implementation ************** + + public TypeMapping getTypeMapping() { + return getOwner().getTypeMapping(); + } + + public Table getDbTable(String tableName) { + return this.getOwner().getDbTable(tableName); + } + + public String getDefaultColumnName() { + Column column = resolveOverriddenColumn(); + if (column == null) { + return getName(); + } + return column.getName(); + } + + + //************* BaseColumn.Owner implementation ************** + + public String getDefaultTableName() { + Column column = resolveOverriddenColumn(); + if (column != null) { + String tableName = column.getSpecifiedTable(); + if (tableName != null) { + return tableName; + } + } + return getOwner().getDefaultTableName(); + } + + protected Column resolveOverriddenColumn() { + return isVirtual() ? getOwner().resolveOverriddenColumn(getName()) : null; + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + + //***************** OrmColumn.Owner implementation **************** + + public XmlColumn getResourceColumn() { + return this.getResourceOverride().getColumn(); + } + + protected boolean isColumnSpecified() { + return getResourceColumn() != null; + } + + public void addResourceColumn() { + this.getResourceOverride().setColumn(OrmFactory.eINSTANCE.createXmlColumn()); + } + + public void removeResourceColumn() { + this.getResourceOverride().setColumn(null); + } + + + // **************** AttributeOverride2_0 impl ***************************** + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean newValue) { + boolean oldValue = this.mappedByRelationship; + this.mappedByRelationship = newValue; + firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, oldValue, newValue); + } + + protected boolean calculateMappedByRelationship() { + for (SingleRelationshipMapping2_0 each : getMapsIdRelationships()) { + if (getName() == null) { + return false; + } + + // overrideable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + String qualifier = + (getName().indexOf('.') > 0) ? + getName().substring(0, getName().indexOf('.')) + : getName(); + return qualifier.equals(each.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue()); + } + return false; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** resource -> context *********************************** + + public void update(XmlAttributeOverride xmlAttributeOverride) { + super.update(xmlAttributeOverride); + this.column.update(xmlAttributeOverride.getColumn()); + setMappedByRelationship(calculateMappedByRelationship()); + } + + + //****************** validation ******************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + // [JPA 2.0] if the column is specified, or if the override is not mapped by a relationship, + // then the column is validated. + // (In JPA 1.0, the column will always be validated, since the override is never mapped by a + // relationship) + if (isColumnSpecified() || ! isMappedByRelationship()) { + getColumn().validate(messages, reporter); + } + + // [JPA 2.0] if the override is mapped by a relationship, then that actually is in itself + // a validation error + // (We prevent implied overrides that are mapped by a relationship ... hopefully) + // (In JPA 1.0, this will never occur) + if (isMappedByRelationship()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ATTRIBUTE_OVERRIDE_MAPPED_BY_RELATIONSHIP_AND_SPECIFIED, + new String[] {}, + this, + getValidationTextRange())); + } + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(this, column, textRange); + } + + public IMessage buildTableNotValidMessage(BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(this, column, textRange); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java new file mode 100644 index 0000000000..59e42b7749 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java @@ -0,0 +1,383 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.emf.common.util.EList; +import org.eclipse.jpt.core.context.AttributeOverride; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmAttributeOverride; +import org.eclipse.jpt.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.context.orm.VirtualXmlAttributeOverride; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlAttributeOverride; +import org.eclipse.jpt.core.resource.orm.XmlColumn; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmAttributeOverrideContainer + extends AbstractOrmXmlContextNode + implements OrmAttributeOverrideContainer +{ + protected final List<OrmAttributeOverride> specifiedAttributeOverrides; + + protected final List<OrmAttributeOverride> virtualAttributeOverrides; + + protected final Owner owner; + + + public GenericOrmAttributeOverrideContainer(XmlContextNode parent, Owner owner) { + super(parent); + this.owner = owner; + this.specifiedAttributeOverrides = new ArrayList<OrmAttributeOverride>(); + this.virtualAttributeOverrides = new ArrayList<OrmAttributeOverride>(); + this.initializeSpecifiedAttributeOverrides(); + this.initializeVirtualAttributeOverrides(); + } + + + public void initializeFromAttributeOverrideContainer(OrmAttributeOverrideContainer oldContainer) { + int index = 0; + for (OrmAttributeOverride attributeOverride : CollectionTools.iterable(oldContainer.specifiedAttributeOverrides())) { + OrmAttributeOverride newAttributeOverride = addSpecifiedAttributeOverride(index++); + newAttributeOverride.setName(attributeOverride.getName()); + newAttributeOverride.getColumn().initializeFrom(attributeOverride.getColumn()); + } + } + + protected Owner getOwner() { + return this.owner; + } + + protected EList<XmlAttributeOverride> getResourceAttributeOverrides() { + return getOwner().getResourceAttributeOverrides(); + } + + @SuppressWarnings("unchecked") + public ListIterator<OrmAttributeOverride> attributeOverrides() { + return new CompositeListIterator<OrmAttributeOverride>(specifiedAttributeOverrides(), virtualAttributeOverrides()); + } + + public int attributeOverridesSize() { + return this.specifiedAttributeOverridesSize() + this.virtualAttributeOverridesSize(); + } + + public ListIterator<OrmAttributeOverride> virtualAttributeOverrides() { + return new CloneListIterator<OrmAttributeOverride>(this.virtualAttributeOverrides); + } + + public int virtualAttributeOverridesSize() { + return this.virtualAttributeOverrides.size(); + } + + protected void addVirtualAttributeOverride(OrmAttributeOverride attributeOverride) { + addItemToList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST); + } + + protected void removeVirtualAttributeOverride(OrmAttributeOverride attributeOverride) { + removeItemFromList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST); + } + + protected OrmAttributeOverride setAttributeOverrideVirtual(boolean virtual, OrmAttributeOverride attributeOverride) { + if (virtual) { + return setAttributeOverrideVirtual(attributeOverride); + } + return setAttributeOverrideSpecified(attributeOverride); + } + + protected OrmAttributeOverride setAttributeOverrideVirtual(OrmAttributeOverride attributeOverride) { + int index = this.specifiedAttributeOverrides.indexOf(attributeOverride); + this.specifiedAttributeOverrides.remove(index); + String attributeOverrideName = attributeOverride.getName(); + //add the virtual attribute override so that I can control the order that change notification is sent. + //otherwise when we remove the annotation from java we will get an update and add the attribute override + //during the update. This causes the UI to be flaky, since change notification might not occur in the correct order + OrmAttributeOverride virtualAttributeOverride = null; + if (attributeOverrideName != null) { + for (String name : CollectionTools.iterable(allOverridableAttributeNames())) { + if (name.equals(attributeOverrideName)) { + //store the virtualAttributeOverride so we can fire change notification later + virtualAttributeOverride = buildVirtualAttributeOverride(name); + this.virtualAttributeOverrides.add(virtualAttributeOverride); + } + } + } + + this.getResourceAttributeOverrides().remove(index); + fireItemRemoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, attributeOverride); + + if (virtualAttributeOverride != null) { + fireItemAdded(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, virtualAttributeOverridesSize() - 1, virtualAttributeOverride); + } + return virtualAttributeOverride; + } + + protected OrmAttributeOverride setAttributeOverrideSpecified(OrmAttributeOverride oldAttributeOverride) { + int index = specifiedAttributeOverridesSize(); + XmlAttributeOverride xmlAttributeOverride = OrmFactory.eINSTANCE.createXmlAttributeOverride(); + OrmAttributeOverride newAttributeOverride = buildAttributeOverride(xmlAttributeOverride); + this.specifiedAttributeOverrides.add(index, newAttributeOverride); + + this.getResourceAttributeOverrides().add(xmlAttributeOverride); + + int defaultIndex = this.virtualAttributeOverrides.indexOf(oldAttributeOverride); + this.virtualAttributeOverrides.remove(defaultIndex); + + newAttributeOverride.setName(oldAttributeOverride.getName()); + newAttributeOverride.getColumn().setSpecifiedName(oldAttributeOverride.getColumn().getName()); + + this.fireItemRemoved(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, defaultIndex, oldAttributeOverride); + this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, newAttributeOverride); + + return newAttributeOverride; + } + + public ListIterator<OrmAttributeOverride> specifiedAttributeOverrides() { + return new CloneListIterator<OrmAttributeOverride>(this.specifiedAttributeOverrides); + } + + public int specifiedAttributeOverridesSize() { + return this.specifiedAttributeOverrides.size(); + } + + protected OrmAttributeOverride addSpecifiedAttributeOverride(int index) { + XmlAttributeOverride xmlAttributeOverride = OrmFactory.eINSTANCE.createXmlAttributeOverride(); + OrmAttributeOverride attributeOverride = buildAttributeOverride(xmlAttributeOverride); + this.specifiedAttributeOverrides.add(index, attributeOverride); + this.getResourceAttributeOverrides().add(index, xmlAttributeOverride); + this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, attributeOverride); + return attributeOverride; + } + + protected void addSpecifiedAttributeOverride(int index, OrmAttributeOverride attributeOverride) { + addItemToList(index, attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST); + } + + protected void addSpecifiedAttributeOverride(OrmAttributeOverride attributeOverride) { + this.addSpecifiedAttributeOverride(this.specifiedAttributeOverrides.size(), attributeOverride); + } + + protected void removeSpecifiedAttributeOverride_(OrmAttributeOverride attributeOverride) { + removeItemFromList(attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST); + } + + public void moveSpecifiedAttributeOverride(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedAttributeOverrides, targetIndex, sourceIndex); + this.getResourceAttributeOverrides().move(targetIndex, sourceIndex); + fireItemMoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, targetIndex, sourceIndex); + } + + public OrmAttributeOverride getAttributeOverrideNamed(String name) { + return (OrmAttributeOverride) getOverrideNamed(name, attributeOverrides()); + } + + public boolean containsAttributeOverride(String name) { + return containsOverride(name, attributeOverrides()); + } + + public boolean containsDefaultAttributeOverride(String name) { + return containsOverride(name, virtualAttributeOverrides()); + } + + public boolean containsSpecifiedAttributeOverride(String name) { + return containsOverride(name, specifiedAttributeOverrides()); + } + + private BaseOverride getOverrideNamed(String name, ListIterator<? extends BaseOverride> overrides) { + for (BaseOverride override : CollectionTools.iterable(overrides)) { + String overrideName = override.getName(); + if (overrideName == null && name == null) { + return override; + } + if (overrideName != null && overrideName.equals(name)) { + return override; + } + } + return null; + } + + private boolean containsOverride(String name, ListIterator<? extends BaseOverride> overrides) { + return getOverrideNamed(name, overrides) != null; + } + + protected Iterator<String> allOverridableAttributeNames() { + return getOwner().allOverridableNames(); + } + + protected void initializeVirtualAttributeOverrides() { + for (String name : CollectionTools.iterable(allOverridableAttributeNames())) { + OrmAttributeOverride ormAttributeOverride = getAttributeOverrideNamed(name); + if (ormAttributeOverride == null) { + this.virtualAttributeOverrides.add(buildVirtualAttributeOverride(name)); + } + } + } + + protected void initializeSpecifiedAttributeOverrides() { + for (XmlAttributeOverride attributeOverride : this.getResourceAttributeOverrides()) { + this.specifiedAttributeOverrides.add(buildAttributeOverride(attributeOverride)); + } + } + + public void update() { + this.updateSpecifiedAttributeOverrides(); + this.updateVirtualAttributeOverrides(); + } + + protected OrmAttributeOverride buildVirtualAttributeOverride(String name) { + return buildAttributeOverride(buildVirtualXmlAttributeOverride(name)); + } + + protected XmlAttributeOverride buildVirtualXmlAttributeOverride(String name) { + Column column = resolveOverriddenColumn(name); + XmlColumn xmlColumn = getOwner().buildVirtualXmlColumn(column, name, getOwner().getTypeMapping().isMetadataComplete()); + return new VirtualXmlAttributeOverride(name, xmlColumn); + } + + private Column resolveOverriddenColumn(String attributeOverrideName) { + return getOwner().resolveOverriddenColumn(attributeOverrideName); + } + + protected void updateSpecifiedAttributeOverrides() { + // make a copy of the XML overrides (to prevent ConcurrentModificationException) + Iterator<XmlAttributeOverride> xmlOverrides = new CloneIterator<XmlAttributeOverride>(this.getResourceAttributeOverrides()); + + for (Iterator<OrmAttributeOverride> contextOverrides = this.specifiedAttributeOverrides(); contextOverrides.hasNext(); ) { + OrmAttributeOverride contextOverride = contextOverrides.next(); + if (xmlOverrides.hasNext()) { + contextOverride.update(xmlOverrides.next()); + } + else { + removeSpecifiedAttributeOverride_(contextOverride); + } + } + + while (xmlOverrides.hasNext()) { + addSpecifiedAttributeOverride(buildAttributeOverride(xmlOverrides.next())); + } + } + + protected void updateVirtualAttributeOverrides() { + Iterator<String> overridableAttributes = allOverridableAttributeNames(); + ListIterator<OrmAttributeOverride> virtualAttributeOverridesCopy = virtualAttributeOverrides(); + + for (String name : CollectionTools.iterable(overridableAttributes)) { + OrmAttributeOverride ormAttributeOverride = getAttributeOverrideNamed(name); + if (ormAttributeOverride != null && !ormAttributeOverride.isVirtual()) { + continue; + } + if (ormAttributeOverride != null) { + if (virtualAttributeOverridesCopy.hasNext()) { + OrmAttributeOverride virtualAttributeOverride = virtualAttributeOverridesCopy.next(); + virtualAttributeOverride.update(buildVirtualXmlAttributeOverride(name)); + } + else { + addVirtualAttributeOverride(buildVirtualAttributeOverride(name)); + } + } + else { + addVirtualAttributeOverride(buildVirtualAttributeOverride(name)); + } + } + for (OrmAttributeOverride virtualAttributeOverride : CollectionTools.iterable(virtualAttributeOverridesCopy)) { + removeVirtualAttributeOverride(virtualAttributeOverride); + } + } + + protected OrmAttributeOverride buildAttributeOverride(XmlAttributeOverride attributeOverride) { + return getXmlContextNodeFactory().buildOrmAttributeOverride(this, createAttributeOverrideOwner(), attributeOverride); + } + + protected AttributeOverride.Owner createAttributeOverrideOwner() { + return new AttributeOverrideOwner(); + } + + + //************ validation *************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + for (Iterator<OrmAttributeOverride> stream = this.attributeOverrides(); stream.hasNext(); ) { + stream.next().validate(messages, reporter); + } + } + + public TextRange getValidationTextRange() { + return getOwner().getValidationTextRange(); + } + + + protected class AttributeOverrideOwner implements AttributeOverride.Owner { + + public Column resolveOverriddenColumn(String attributeName) { + if (attributeName == null) { + return null; + } + return GenericOrmAttributeOverrideContainer.this.resolveOverriddenColumn(attributeName); + } + + public boolean isVirtual(BaseOverride override) { + return GenericOrmAttributeOverrideContainer.this.virtualAttributeOverrides.contains(override); + } + + public BaseOverride setVirtual(boolean virtual, BaseOverride override) { + return GenericOrmAttributeOverrideContainer.this.setAttributeOverrideVirtual(virtual, (OrmAttributeOverride) override); + } + + public TypeMapping getTypeMapping() { + return getOwner().getTypeMapping(); + } + + public Iterator<String> allOverridableAttributeNames() { + return GenericOrmAttributeOverrideContainer.this.allOverridableAttributeNames(); + } + + public boolean tableNameIsInvalid(String tableName) { + return getOwner().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getOwner().candidateTableNames(); + } + + public String getDefaultTableName() { + return getOwner().getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + return getOwner().buildColumnTableNotValidMessage(override, column, textRange); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + return getOwner().buildColumnUnresolvedNameMessage(override, column, textRange); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java new file mode 100644 index 0000000000..406105dc9f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBasicMapping; +import org.eclipse.jpt.core.resource.orm.XmlBasic; + + +public class GenericOrmBasicMapping extends AbstractOrmBasicMapping<XmlBasic> +{ + + public GenericOrmBasicMapping(OrmPersistentAttribute parent, XmlBasic resourceMapping) { + super(parent, resourceMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmCascade.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmCascade.java new file mode 100644 index 0000000000..149b0031e8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmCascade.java @@ -0,0 +1,281 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmRelationshipMapping; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.jpa2.context.Cascade2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmCascade2_0; +import org.eclipse.jpt.core.resource.orm.AbstractXmlRelationshipMapping; +import org.eclipse.jpt.core.resource.orm.CascadeType; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.utility.TextRange; + + +public class GenericOrmCascade + extends AbstractOrmXmlContextNode + implements OrmCascade2_0 +{ + protected boolean all; + + protected boolean persist; + + protected boolean merge; + + protected boolean remove; + + protected boolean refresh; + + /* JPA 2.0 */ + protected boolean detach; + + protected final AbstractXmlRelationshipMapping relationshipMapping; + + + public GenericOrmCascade(OrmRelationshipMapping parent, AbstractXmlRelationshipMapping relationshipMapping) { + super(parent); + this.relationshipMapping = relationshipMapping; + CascadeType cascade = getResourceCascade(); + this.all = this.getResourceAll(cascade); + this.persist = this.getResourcePersist(cascade); + this.merge = this.getResourceMerge(cascade); + this.remove = this.getResourceRemove(cascade); + this.refresh = this.getResourceRefresh(cascade); + this.detach = this.getResourceDetach(cascade); + } + + + public void initializeFrom(Cascade2_0 oldCascade) { + setAll(oldCascade.isAll()); + setPersist(oldCascade.isPersist()); + setMerge(oldCascade.isMerge()); + setRemove(oldCascade.isRemove()); + setRefresh(oldCascade.isRefresh()); + setDetach(oldCascade.isDetach()); + } + + public boolean isAll() { + return this.all; + } + + public void setAll(boolean newAll) { + boolean oldAll = this.all; + this.all = newAll; + if (oldAll != newAll) { + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadeAll(newAll); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newAll != false) { + addResourceCascade(); + getResourceCascade().setCascadeAll(newAll); + } + } + firePropertyChanged(ALL_PROPERTY, oldAll, newAll); + } + + protected void setAll_(boolean newAll) { + boolean oldAll = this.all; + this.all = newAll; + firePropertyChanged(ALL_PROPERTY, oldAll, newAll); + } + + public boolean isPersist() { + return this.persist; + } + + public void setPersist(boolean newPersist) { + boolean oldPersist = this.persist; + this.persist = newPersist; + if (oldPersist != newPersist) { + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadePersist(newPersist); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newPersist != false) { + addResourceCascade(); + getResourceCascade().setCascadePersist(newPersist); + } + } + firePropertyChanged(PERSIST_PROPERTY, oldPersist, newPersist); + } + + protected void setPersist_(boolean newPersist) { + boolean oldPersist = this.persist; + this.persist = newPersist; + firePropertyChanged(PERSIST_PROPERTY, oldPersist, newPersist); + } + + public boolean isMerge() { + return this.merge; + } + + public void setMerge(boolean newMerge) { + boolean oldMerge = this.merge; + this.merge = newMerge; + if (oldMerge != newMerge) { + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadeMerge(newMerge); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newMerge != false) { + addResourceCascade(); + getResourceCascade().setCascadeMerge(newMerge); + } + } + firePropertyChanged(MERGE_PROPERTY, oldMerge, newMerge); + } + + protected void setMerge_(boolean newMerge) { + boolean oldMerge = this.merge; + this.merge = newMerge; + firePropertyChanged(MERGE_PROPERTY, oldMerge, newMerge); + } + + public boolean isRemove() { + return this.remove; + } + + public void setRemove(boolean newRemove) { + boolean oldRemove = this.remove; + if (oldRemove != newRemove) { + this.remove = newRemove; + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadeRemove(newRemove); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newRemove != false) { + addResourceCascade(); + getResourceCascade().setCascadeRemove(newRemove); + } + } + firePropertyChanged(REMOVE_PROPERTY, oldRemove, newRemove); + } + + protected void setRemove_(boolean newRemove) { + boolean oldRemove = this.remove; + this.remove = newRemove; + firePropertyChanged(REMOVE_PROPERTY, oldRemove, newRemove); + } + + public boolean isRefresh() { + return this.refresh; + } + + public void setRefresh(boolean newRefresh) { + boolean oldRefresh = this.refresh; + this.refresh = newRefresh; + if (oldRefresh != newRefresh) { + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadeRefresh(newRefresh); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newRefresh != false) { + addResourceCascade(); + getResourceCascade().setCascadeRefresh(newRefresh); + } + } + firePropertyChanged(REFRESH_PROPERTY, oldRefresh, newRefresh); + } + + protected void setRefresh_(boolean newRefresh) { + boolean oldRefresh = this.refresh; + this.refresh = newRefresh; + firePropertyChanged(REFRESH_PROPERTY, oldRefresh, newRefresh); + } + + public boolean isDetach() { + return this.detach; + } + + public void setDetach(boolean newDetach) { + boolean oldDetach = this.detach; + this.detach = newDetach; + if (oldDetach != newDetach) { + if (this.getResourceCascade() != null) { + this.getResourceCascade().setCascadeDetach(newDetach); + if (this.getResourceCascade().isUnset()) { + removeResourceCascade(); + } + } + else if (newDetach != false) { + addResourceCascade(); + getResourceCascade().setCascadeDetach(newDetach); + } + } + firePropertyChanged(DETACH_PROPERTY, oldDetach, newDetach); + } + + protected void setDetach_(boolean newDetach) { + boolean oldDetach = this.detach; + this.detach = newDetach; + firePropertyChanged(DETACH_PROPERTY, oldDetach, newDetach); + } + + protected CascadeType getResourceCascade() { + return this.relationshipMapping.getCascade(); + } + + protected void removeResourceCascade() { + this.relationshipMapping.setCascade(null); + } + + protected void addResourceCascade() { + this.relationshipMapping.setCascade(OrmFactory.eINSTANCE.createCascadeType()); + } + + public void update() { + CascadeType cascade = getResourceCascade(); + this.setAll_(this.getResourceAll(cascade)); + this.setPersist_(this.getResourcePersist(cascade)); + this.setMerge_(this.getResourceMerge(cascade)); + this.setRemove_(this.getResourceRemove(cascade)); + this.setRefresh_(this.getResourceRefresh(cascade)); + this.setDetach_(this.getResourceDetach(cascade)); + } + + protected boolean getResourceAll(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadeAll(); + } + + protected boolean getResourcePersist(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadePersist(); + } + + protected boolean getResourceMerge(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadeMerge(); + } + + protected boolean getResourceRemove(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadeRemove(); + } + + protected boolean getResourceRefresh(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadeRefresh(); + } + + protected boolean getResourceDetach(CascadeType cascade) { + return cascade == null ? false : cascade.isCascadeDetach(); + } + + public TextRange getValidationTextRange() { + return this.getResourceCascade().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmColumn.java new file mode 100644 index 0000000000..ef90cfc1df --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmColumn.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.Column; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmColumn; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBaseColumn; +import org.eclipse.jpt.core.resource.orm.XmlColumn; + +public class GenericOrmColumn extends AbstractOrmBaseColumn<XmlColumn> implements OrmColumn +{ + protected Integer specifiedLength; + + protected Integer specifiedPrecision; + + protected Integer specifiedScale; + + public GenericOrmColumn(XmlContextNode parent, OrmColumn.Owner owner) { + super(parent, owner); + } + + @Override + public OrmColumn.Owner getOwner() { + return (OrmColumn.Owner) super.getOwner(); + } + + public void initializeFrom(Column oldColumn) { + super.initializeFrom(oldColumn); + setSpecifiedLength(oldColumn.getSpecifiedLength()); + setSpecifiedPrecision(oldColumn.getSpecifiedPrecision()); + setSpecifiedScale(oldColumn.getSpecifiedScale()); + } + + public int getLength() { + return (this.getSpecifiedLength() == null) ? getDefaultLength() : this.getSpecifiedLength().intValue(); + } + + public int getDefaultLength() { + return Column.DEFAULT_LENGTH; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + if (this.valuesAreDifferent(oldSpecifiedLength, newSpecifiedLength)) { + if (this.getResourceColumn() != null) { + this.getResourceColumn().setLength(newSpecifiedLength); + this.removeResourceColumnIfFeaturesUnset(); + } + else if (newSpecifiedLength != null) { + addResourceColumn(); + getResourceColumn().setLength(newSpecifiedLength); + } + } + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + protected void setSpecifiedLength_(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + public int getPrecision() { + return (this.getSpecifiedPrecision() == null) ? getDefaultPrecision() : this.getSpecifiedPrecision().intValue(); + } + + public int getDefaultPrecision() { + return Column.DEFAULT_PRECISION; + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + public void setSpecifiedPrecision(Integer newSpecifiedPrecision) { + Integer oldSpecifiedPrecision = this.specifiedPrecision; + this.specifiedPrecision = newSpecifiedPrecision; + if (this.valuesAreDifferent(oldSpecifiedPrecision, newSpecifiedPrecision)) { + if (this.getResourceColumn() != null) { + this.getResourceColumn().setPrecision(newSpecifiedPrecision); + this.removeResourceColumnIfFeaturesUnset(); + } + else if (newSpecifiedPrecision != null) { + addResourceColumn(); + getResourceColumn().setPrecision(newSpecifiedPrecision); + } + } + firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, oldSpecifiedPrecision, newSpecifiedPrecision); + } + + protected void setSpecifiedPrecision_(Integer newSpecifiedPrecision) { + Integer oldSpecifiedPrecision = this.specifiedPrecision; + this.specifiedPrecision = newSpecifiedPrecision; + firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, oldSpecifiedPrecision, newSpecifiedPrecision); + } + + public int getScale() { + return (this.getSpecifiedScale() == null) ? getDefaultScale() : this.getSpecifiedScale().intValue(); + } + + public int getDefaultScale() { + return Column.DEFAULT_SCALE; + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + public void setSpecifiedScale(Integer newSpecifiedScale) { + Integer oldSpecifiedScale = this.specifiedScale; + this.specifiedScale = newSpecifiedScale; + if (this.valuesAreDifferent(oldSpecifiedScale, newSpecifiedScale)) { + if (this.getResourceColumn() != null) { + this.getResourceColumn().setScale(newSpecifiedScale); + this.removeResourceColumnIfFeaturesUnset(); + } + else if (newSpecifiedScale != null) { + addResourceColumn(); + getResourceColumn().setScale(newSpecifiedScale); + } + } + firePropertyChanged(SPECIFIED_SCALE_PROPERTY, oldSpecifiedScale, newSpecifiedScale); + } + + protected void setSpecifiedScale_(Integer newSpecifiedScale) { + Integer oldSpecifiedScale = this.specifiedScale; + this.specifiedScale = newSpecifiedScale; + firePropertyChanged(SPECIFIED_SCALE_PROPERTY, oldSpecifiedScale, newSpecifiedScale); + } + + @Override + protected XmlColumn getResourceColumn() { + return getOwner().getResourceColumn(); + } + + @Override + protected void addResourceColumn() { + getOwner().addResourceColumn(); + } + + @Override + protected void removeResourceColumn() { + getOwner().removeResourceColumn(); + } + + @Override + public void initialize(XmlColumn column) { + super.initialize(column); + this.specifiedLength = this.getResourceLength(column); + this.specifiedPrecision = this.getResourcePrecision(column); + this.specifiedScale = this.getResourceScale(column); + } + + @Override + public void update(XmlColumn column) { + super.update(column); + this.setSpecifiedLength_(this.getResourceLength(column)); + this.setSpecifiedPrecision_(this.getResourcePrecision(column)); + this.setSpecifiedScale_(this.getResourceScale(column)); + } + + protected Integer getResourceLength(XmlColumn column) { + return column == null ? null : column.getLength(); + } + + protected Integer getResourcePrecision(XmlColumn column) { + return column == null ? null : column.getPrecision(); + } + + protected Integer getResourceScale(XmlColumn column) { + return column == null ? null : column.getScale(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java new file mode 100644 index 0000000000..f917ea3900 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.DiscriminatorColumn; +import org.eclipse.jpt.core.context.DiscriminatorType; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmDiscriminatorColumn; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmNamedColumn; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlDiscriminatorColumn; +import org.eclipse.jpt.core.resource.orm.XmlEntity; + +public class GenericOrmDiscriminatorColumn extends AbstractOrmNamedColumn<XmlDiscriminatorColumn> + implements OrmDiscriminatorColumn +{ + + protected DiscriminatorType specifiedDiscriminatorType; + + protected DiscriminatorType defaultDiscriminatorType; + + protected Integer specifiedLength; + + protected int defaultLength; + + protected XmlEntity entity; + + public GenericOrmDiscriminatorColumn(XmlContextNode parent, OrmDiscriminatorColumn.Owner owner) { + super(parent, owner); + } + + @Override + public OrmDiscriminatorColumn.Owner getOwner() { + return (OrmDiscriminatorColumn.Owner) super.getOwner(); + } + + public DiscriminatorType getDiscriminatorType() { + return (this.getSpecifiedDiscriminatorType() == null) ? this.getDefaultDiscriminatorType() : this.getSpecifiedDiscriminatorType(); + } + + public DiscriminatorType getDefaultDiscriminatorType() { + return this.defaultDiscriminatorType; + } + + protected void setDefaultDiscriminatorType(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.defaultDiscriminatorType; + this.defaultDiscriminatorType = discriminatorType; + firePropertyChanged(DEFAULT_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + public DiscriminatorType getSpecifiedDiscriminatorType() { + return this.specifiedDiscriminatorType; + } + + public void setSpecifiedDiscriminatorType(DiscriminatorType newSpecifiedDiscriminatorType) { + DiscriminatorType oldDiscriminatorType = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = newSpecifiedDiscriminatorType; + if (oldDiscriminatorType != newSpecifiedDiscriminatorType) { + if (this.getResourceColumn() != null) { + this.getResourceColumn().setDiscriminatorType(DiscriminatorType.toOrmResourceModel(newSpecifiedDiscriminatorType)); + this.removeResourceColumnIfFeaturesUnset(); + } + else if (newSpecifiedDiscriminatorType != null) { + addResourceColumn(); + this.getResourceColumn().setDiscriminatorType(DiscriminatorType.toOrmResourceModel(newSpecifiedDiscriminatorType)); + } + } + firePropertyChanged(DiscriminatorColumn.SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, oldDiscriminatorType, newSpecifiedDiscriminatorType); + } + + protected void setSpecifiedDiscriminatorType_(DiscriminatorType newSpecifiedDiscriminatorType) { + DiscriminatorType oldDiscriminatorType = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = newSpecifiedDiscriminatorType; + firePropertyChanged(DiscriminatorColumn.SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, oldDiscriminatorType, newSpecifiedDiscriminatorType); + } + + public int getLength() { + return (this.getSpecifiedLength() == null) ? this.getDefaultLength() : this.getSpecifiedLength().intValue(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int defaultLength) { + int old = this.defaultLength; + this.defaultLength = defaultLength; + firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, defaultLength); + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + if (this.valuesAreDifferent(oldSpecifiedLength, newSpecifiedLength)) { + if (this.getResourceColumn() != null) { + this.getResourceColumn().setLength(newSpecifiedLength); + this.removeResourceColumnIfFeaturesUnset(); + } + else if (newSpecifiedLength != null) { + addResourceColumn(); + getResourceColumn().setLength(newSpecifiedLength); + } + } + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + protected void setSpecifiedLength_(Integer newSpecifiedLength) { + Integer oldSpecifiedLength = this.specifiedLength; + this.specifiedLength = newSpecifiedLength; + firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, oldSpecifiedLength, newSpecifiedLength); + } + + + @Override + public XmlDiscriminatorColumn getResourceColumn() { + return this.entity.getDiscriminatorColumn(); + } + + @Override + protected void addResourceColumn() { + this.entity.setDiscriminatorColumn(OrmFactory.eINSTANCE.createXmlDiscriminatorColumn()); + } + + @Override + protected void removeResourceColumn() { + this.entity.setDiscriminatorColumn(null); + } + + public boolean isResourceSpecified() { + return getResourceColumn() != null; + } + + public void initialize(XmlEntity xmlEntity) { + this.entity = xmlEntity; + this.initialize(this.getResourceColumn()); + } + + public void update(XmlEntity xmlEntity) { + this.entity = xmlEntity; + this.update(this.getResourceColumn()); + } + + + @Override + protected void initialize(XmlDiscriminatorColumn column) { + super.initialize(column); + this.defaultDiscriminatorType = this.buildDefaultDiscriminatorType(); + this.defaultLength = this.buildDefaultLength(); + this.specifiedLength = this.getResourceLength(column); + this.specifiedDiscriminatorType = this.getResourceDiscriminatorType(column); + } + + @Override + protected void update(XmlDiscriminatorColumn column) { + //don't call super because postUpdate() handles updating the default column name + this.setSpecifiedName_(this.getResourceColumnName(column)); + this.setColumnDefinition_(this.getResourceColumnDefinition(column)); + this.setSpecifiedLength_(this.getResourceLength(column)); + this.setSpecifiedDiscriminatorType_(this.getResourceDiscriminatorType(column)); + } + + @Override + /** + * Using postUpdate since these defaults are dependent on the entity hierarchy + */ + public void postUpdate() { + super.postUpdate(); + this.setDefaultName(this.buildDefaultName()); + this.setDefaultDiscriminatorType(this.buildDefaultDiscriminatorType()); + this.setDefaultLength(this.buildDefaultLength()); + } + + protected Integer getResourceLength(XmlDiscriminatorColumn column) { + return column == null ? null : column.getLength(); + } + + protected DiscriminatorType getResourceDiscriminatorType(XmlDiscriminatorColumn column) { + return column == null ? null : DiscriminatorType.fromOrmResourceModel(column.getDiscriminatorType()); + } + + protected int buildDefaultLength() { + return this.getOwner().getDefaultLength(); + } + + protected DiscriminatorType buildDefaultDiscriminatorType() { + return this.getOwner().getDefaultDiscriminatorType(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java new file mode 100644 index 0000000000..f0c0c8d0a5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Oracle. - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmEmbeddable; +import org.eclipse.jpt.core.internal.jpa1.context.java.GenericJavaEmbeddable; +import org.eclipse.jpt.core.resource.orm.XmlEmbeddable; +import org.eclipse.jpt.utility.internal.ArrayTools; + + +public class GenericOrmEmbeddable + extends AbstractOrmEmbeddable +{ + public GenericOrmEmbeddable(OrmPersistentType parent, XmlEmbeddable resourceMapping) { + super(parent, resourceMapping); + } + + @Override + public boolean attributeMappingKeyAllowed(String attributeMappingKey) { + return ArrayTools.contains(GenericJavaEmbeddable.ALLOWED_ATTRIBUTE_MAPPING_KEYS, attributeMappingKey); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java new file mode 100644 index 0000000000..21619f2025 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.core.context.orm.OrmEmbeddedIdMapping; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBaseEmbeddedMapping; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.EmbeddedIdMapping2_0; +import org.eclipse.jpt.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.XmlEmbeddedId; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.Tools; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper; +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.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericOrmEmbeddedIdMapping + extends AbstractOrmBaseEmbeddedMapping<XmlEmbeddedId> + implements EmbeddedIdMapping2_0, OrmEmbeddedIdMapping +{ + /* 2.0 feature - a relationship may map this embedded id */ + protected boolean mappedByRelationship; + + + public GenericOrmEmbeddedIdMapping(OrmPersistentAttribute parent, XmlEmbeddedId resourceMapping) { + super(parent, resourceMapping); + this.mappedByRelationship = calculateMappedByRelationship(); + } + + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmEmbeddedIdMapping(this); + } + + public int getXmlSequence() { + return 10; + } + + + //*************** AttributeMapping implementation ********************* + + public String getKey() { + return MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY; + } + + public void addToResourceModel(Attributes resourceAttributes) { + resourceAttributes.getEmbeddedIds().add(this.resourceAttributeMapping); + } + + public void removeFromResourceModel(Attributes resourceAttributes) { + resourceAttributes.getEmbeddedIds().remove(this.resourceAttributeMapping); + } + + + // **************** EmbeddedId2_0 impl ************************************ + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean newValue) { + boolean oldValue = this.mappedByRelationship; + this.mappedByRelationship = newValue; + firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, oldValue, newValue); + } + + protected boolean calculateMappedByRelationship() { + for (SingleRelationshipMapping2_0 each : getMapsIdRelationships()) { + if (Tools.valuesAreEqual(getName(), each.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue())) { + return true; + } + } + return false; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() { + return new FilteringIterable<SingleRelationshipMapping2_0>( + new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>( + new CompositeIterable<AttributeMapping>( + getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)))) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** overrides ********************************************* + + @Override + protected Iterator<String> embeddableOverrideableAttributeMappingNames() { + return (isMappedByRelationship()) ? + EmptyIterator.<String>instance() + : super.embeddableOverrideableAttributeMappingNames(); + } + + @Override + protected OrmAttributeOverrideContainer.Owner buildAttributeOverrideContainerOwner() { + return new AttributeOverrideContainerOwner(); + } + + + protected class AttributeOverrideContainerOwner + extends AbstractOrmBaseEmbeddedMapping.AttributeOverrideContainerOwner + { + @Override + public Iterator<String> allOverridableNames() { + return (GenericOrmEmbeddedIdMapping.this.isMappedByRelationship()) ? + EmptyIterator.<String>instance() + : super.allOverridableNames(); + } + + @Override + protected Iterator<String> allOverridableAttributeNames_(TypeMapping typeMapping) { + final Collection<String> mappedByRelationshipAttributes = CollectionTools.collection( + new TransformationIterator<SingleRelationshipMapping2_0, String>(getMapsIdRelationships()) { + @Override + protected String transform(SingleRelationshipMapping2_0 next) { + return next.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue(); + } + }); + return new FilteringIterator<String>(super.allOverridableAttributeNames_(typeMapping)) { + @Override + protected boolean accept(String o) { + if (mappedByRelationshipAttributes.isEmpty()) { + return true; + } + // overrideable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + String qualifier = + (o.indexOf('.') > 0) ? + o.substring(0, o.indexOf('.')) + : o; + return ! mappedByRelationshipAttributes.contains(qualifier); + } + }; + } + } + + + // **************** resource -> context *********************************** + + @Override + public void update() { + super.update(); + setMappedByRelationship(calculateMappedByRelationship()); + } + + + // **************** validation ******************************************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + // [JPA 2.0] if the embedded id is mapped by a relationship, then any specified + // attribute overrides are in error + // (in JPA 1.0, this will obviously never be reached) + if (isMappedByRelationship() + && getAttributeOverrideContainer().specifiedAttributeOverridesSize() > 0) { + TextRange textRange = getAttributeOverrideContainer().getValidationTextRange(); + if (!isVirtual()) { + textRange = getAttributeOverrideContainer().specifiedAttributeOverrides().next().getValidationTextRange(); + } + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.EMBEDDED_ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_ATTRIBUTE_OVERRIDES_SPECIFIED, + new String[] {}, + getAttributeOverrideContainer(), + textRange)); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java new file mode 100644 index 0000000000..85bb6269bd --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java @@ -0,0 +1,482 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.emf.common.util.EList; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AssociationOverride; +import org.eclipse.jpt.core.context.AttributeMapping; +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.BaseOverride; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.RelationshipReference; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.java.JavaAssociationOverride; +import org.eclipse.jpt.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.context.orm.OrmTypeMapping; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBaseEmbeddedMapping; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.java.JavaEmbeddedMapping2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmEmbeddedMapping2_0; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.XmlAssociationOverride; +import org.eclipse.jpt.core.resource.orm.XmlEmbedded; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.Transformer; +import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.utility.internal.iterators.SubIteratorWrapper; +import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + + +public class GenericOrmEmbeddedMapping + extends AbstractOrmBaseEmbeddedMapping<XmlEmbedded> + implements OrmEmbeddedMapping2_0 +{ + protected OrmAssociationOverrideContainer associationOverrideContainer; + + public GenericOrmEmbeddedMapping(OrmPersistentAttribute parent, XmlEmbedded resourceMapping) { + super(parent, resourceMapping); + this.associationOverrideContainer = + getXmlContextNodeFactory(). + buildOrmAssociationOverrideContainer( + this, + new AssociationOverrideContainerOwner()); + } + + @Override + public void update() { + super.update(); + getAssociationOverrideContainer().update(); + } + + @Override + public void postUpdate() { + super.postUpdate(); + getAssociationOverrideContainer().postUpdate(); + } + + @Override + public JavaEmbeddedMapping2_0 getJavaEmbeddedMapping() { + return (JavaEmbeddedMapping2_0) super.getJavaEmbeddedMapping(); + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmEmbeddedMapping(this); + } + + public int getXmlSequence() { + return 80; + } + + public String getKey() { + return MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY; + } + + public void addToResourceModel(Attributes resourceAttributes) { + resourceAttributes.getEmbeddeds().add(this.resourceAttributeMapping); + } + + public void removeFromResourceModel(Attributes resourceAttributes) { + resourceAttributes.getEmbeddeds().remove(this.resourceAttributeMapping); + } + + //only putting this in EmbeddedMapping since relationship mappings + //defined within an embedded id class are not supported by the 2.0 spec. + //i.e. the mappedBy choices will not include attributes nested in an embedded mapping + @Override + public Iterator<String> allMappingNames() { + return this.isJpa2_0Compatible() ? + new CompositeIterator<String>(this.getName(),this.allEmbeddableAttributeMappingNames()) : + super.allMappingNames(); + } + + protected Iterator<String> allEmbeddableAttributeMappingNames() { + return this.embeddableOverrideableMappingNames( + new Transformer<AttributeMapping, Iterator<String>>() { + public Iterator<String> transform(AttributeMapping mapping) { + return mapping.allMappingNames(); + } + } + ); + } + + @Override + public AttributeMapping resolveAttributeMapping(String attributeName) { + if (getName() == null) { + return null; + } + AttributeMapping resolvedMapping = super.resolveAttributeMapping(attributeName); + if (resolvedMapping != null) { + return resolvedMapping; + } + if (this.isJpa2_0Compatible()) { + int dotIndex = attributeName.indexOf('.'); + if (dotIndex != -1) { + if (getName().equals(attributeName.substring(0, dotIndex))) { + for (AttributeMapping attributeMapping : CollectionTools.iterable(embeddableAttributeMappings())) { + resolvedMapping = attributeMapping.resolveAttributeMapping(attributeName.substring(dotIndex + 1)); + if (resolvedMapping != null) { + return resolvedMapping; + } + } + } + } + } + return null; + } + + @Override + public RelationshipReference resolveRelationshipReference(String attributeName) { + if (getName() == null) { + return null; + } + if (this.isJpa2_0Compatible()) { + int dotIndex = attributeName.indexOf('.'); + if (dotIndex != -1) { + if (getName().equals(attributeName.substring(0, dotIndex))) { + attributeName = attributeName.substring(dotIndex + 1); + AssociationOverride override = getAssociationOverrideContainer().getAssociationOverrideNamed(attributeName); + if (override != null && !override.isVirtual()) { + return override.getRelationshipReference(); + } + if (this.getTargetEmbeddable() == null) { + return null; + } + return this.getTargetEmbeddable().resolveRelationshipReference(attributeName); + } + } + } + return null; + } + + public OrmAssociationOverrideContainer getAssociationOverrideContainer() { + return this.associationOverrideContainer; + } + + protected JavaAssociationOverride getJavaAssociationOverrideNamed(String attributeName) { + if (getJavaEmbeddedMapping() != null) { + return getJavaEmbeddedMapping().getAssociationOverrideContainer().getAssociationOverrideNamed(attributeName); + } + return null; + } + + + //************* AttributeOverrideContainer.Owner implementation ******************** + + public Iterator<String> allOverridableAssociationNames() { + return new TransformationIterator<RelationshipMapping, String>(this.allOverridableAssociations()) { + @Override + protected String transform(RelationshipMapping overridableAssociation) { + return overridableAssociation.getName(); + } + }; + } + + public Iterator<RelationshipMapping> allOverridableAssociations() { + return (this.getTargetEmbeddable() == null) ? + EmptyIterator.<RelationshipMapping>instance() : + new SubIteratorWrapper<AttributeMapping, RelationshipMapping>(this.allOverridableAssociations_()); + } + + protected Iterator<AttributeMapping> allOverridableAssociations_() { + return new FilteringIterator<AttributeMapping>(this.getTargetEmbeddable().attributeMappings()) { + @Override + protected boolean accept(AttributeMapping o) { + return o.isOverridableAssociationMapping(); + } + }; + } + + + // ********** validation ********** + @Override + protected void validateOverrides(List<IMessage> messages, IReporter reporter) { + super.validateOverrides(messages, reporter); + this.getAssociationOverrideContainer().validate(messages, reporter); + } + + + //********** OrmAssociationOverrideContainer.Owner implementation ********* + + protected class AssociationOverrideContainerOwner + implements OrmAssociationOverrideContainer.Owner + { + public OrmTypeMapping getTypeMapping() { + return GenericOrmEmbeddedMapping.this.getTypeMapping(); + } + + public TypeMapping getOverridableTypeMapping() { + return GenericOrmEmbeddedMapping.this.getTargetEmbeddable(); + } + + public Iterator<String> allOverridableNames() { + TypeMapping typeMapping = getOverridableTypeMapping(); + return (typeMapping == null) ? + EmptyIterator.<String>instance() + : typeMapping.allOverridableAssociationNames(); + } + + public EList<XmlAssociationOverride> getResourceAssociationOverrides() { + return GenericOrmEmbeddedMapping.this.resourceAttributeMapping.getAssociationOverrides(); + } + + public RelationshipReference resolveRelationshipReference(String associationOverrideName) { + if (getPersistentAttribute().isVirtual() && !getTypeMapping().isMetadataComplete()) { + JavaAssociationOverride javaAssociationOverride = getJavaAssociationOverrideNamed(associationOverrideName); + if (javaAssociationOverride != null && !javaAssociationOverride.isVirtual()) { + return javaAssociationOverride.getRelationshipReference(); + } + } + return MappingTools.resolveRelationshipReference(getOverridableTypeMapping(), associationOverrideName); + } + + public boolean tableNameIsInvalid(String tableName) { + return getTypeMapping().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return getTypeMapping().associatedTableNamesIncludingInherited(); + } + + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + return getTypeMapping().getDbTable(tableName); + } + + public String getDefaultTableName() { + return getTypeMapping().getPrimaryTableName(); + } + + public TextRange getValidationTextRange() { + return GenericOrmEmbeddedMapping.this.getValidationTextRange(); + } + + public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) { + if (isVirtual()) { + return this.buildVirtualAttributeColumnTableNotValidMessage(override.getName(), column, textRange); + } + if (override.isVirtual()) { + return this.buildVirtualOverrideColumnTableNotValidMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_TABLE_NOT_VALID, + new String[] { + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, + column, + textRange + ); + } + + protected IMessage buildVirtualAttributeColumnTableNotValidMessage(String overrideName, BaseColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID, + new String[] { + GenericOrmEmbeddedMapping.this.getName(), + overrideName, + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideColumnTableNotValidMessage(String overrideName, BaseColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID, + new String[] { + overrideName, + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY}, + column, + textRange + ); + } + + public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) { + if (isVirtual()) { + return this.buildVirtualAttributeColumnUnresolvedNameMessage(override.getName(), column, textRange); + } + if (override.isVirtual()) { + return this.buildVirtualOverrideColumnUnresolvedNameMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualAttributeColumnUnresolvedNameMessage(String overrideName, NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] { + GenericOrmEmbeddedMapping.this.getName(), + overrideName, + column.getName(), + column.getDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideColumnUnresolvedNameMessage(String overrideName, NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] { + overrideName, + column.getName(), + column.getDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildColumnUnresolvedReferencedColumnNameMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (isVirtual()) { + return this.buildVirtualAttributeColumnUnresolvedReferencedColumnNameMessage(override.getName(), column, textRange); + } + if (override.isVirtual()) { + return this.buildVirtualOverrideColumnUnresolvedReferencedColumnNameMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] { + column.getReferencedColumnName(), + column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualAttributeColumnUnresolvedReferencedColumnNameMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME, + new String[] { + GenericOrmEmbeddedMapping.this.getName(), + overrideName, + column.getReferencedColumnName(), + column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideColumnUnresolvedReferencedColumnNameMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] { + overrideName, + column.getReferencedColumnName(), + column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (isVirtual()) { + return this.buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + if (override.isVirtual()) { + return this.buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {GenericOrmEmbeddedMapping.this.getName(), overrideName}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {overrideName}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(AssociationOverride override, BaseJoinColumn column, TextRange textRange) { + if (isVirtual()) { + return this.buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + if (override.isVirtual()) { + return this.buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(override.getName(), column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {GenericOrmEmbeddedMapping.this.getName(), overrideName}, + column, + textRange + ); + } + + protected IMessage buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(String overrideName, BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {overrideName}, + column, + textRange + ); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEntity.java new file mode 100644 index 0000000000..867a738828 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEntity.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmEntity; +import org.eclipse.jpt.core.jpa2.context.CacheableHolder2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmCacheable2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmXml2_0ContextNodeFactory; +import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.core.resource.orm.XmlEntity; + +public class GenericOrmEntity + extends AbstractOrmEntity + +{ + + protected final OrmCacheable2_0 cacheable; + + public GenericOrmEntity(OrmPersistentType parent, XmlEntity resourceMapping) { + super(parent, resourceMapping); + this.cacheable = ((OrmXml2_0ContextNodeFactory) getXmlContextNodeFactory()).buildOrmCacheable(this, resourceMapping); + } + + public OrmCacheable2_0 getCacheable() { + return this.cacheable; + } + + public boolean calculateDefaultCacheable() { + if (!isMetadataComplete()) { + CacheableHolder2_0 javaEntity = (CacheableHolder2_0) getJavaEntity(); + if (javaEntity != null) { + return javaEntity.getCacheable().isCacheable(); + } + } + + CacheableHolder2_0 parentEntity = (CacheableHolder2_0) getParentEntity(); + if (parentEntity != null) { + return parentEntity.getCacheable().isCacheable(); + } + return ((PersistenceUnit2_0) getPersistenceUnit()).calculateDefaultCacheable(); + } + + @Override + public void update() { + super.update(); + getCacheable().update(); + } +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java new file mode 100644 index 0000000000..ad4abac133 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.EnumType; +import org.eclipse.jpt.core.context.EnumeratedConverter; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmConverter; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlConvertibleMapping; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericOrmEnumeratedConverter extends AbstractOrmXmlContextNode + implements EnumeratedConverter, OrmConverter +{ + protected EnumType specifiedEnumType; + + protected XmlConvertibleMapping resourceConvertibleMapping; + + public GenericOrmEnumeratedConverter(OrmAttributeMapping parent, XmlConvertibleMapping resourceMapping) { + super(parent); + this.initialize(resourceMapping); + } + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.ENUMERATED_CONVERTER; + } + + public EnumType getEnumType() { + return getSpecifiedEnumType() == null ? getDefaultEnumType() : getSpecifiedEnumType(); + } + + public EnumType getDefaultEnumType() { + //there is no default enumType in xml, if you specify the enumerated element, you must + //specify either ORDINAL or STRING + return null; + } + + public EnumType getSpecifiedEnumType() { + return this.specifiedEnumType; + } + + public void setSpecifiedEnumType(EnumType newSpecifiedEnumType) { + EnumType oldSpecifiedEnumType = this.specifiedEnumType; + this.specifiedEnumType = newSpecifiedEnumType; + this.resourceConvertibleMapping.setEnumerated(EnumType.toOrmResourceModel(newSpecifiedEnumType)); + firePropertyChanged(EnumeratedConverter.SPECIFIED_ENUM_TYPE_PROPERTY, oldSpecifiedEnumType, newSpecifiedEnumType); + } + + protected void setSpecifiedEnumType_(EnumType newSpecifiedEnumType) { + EnumType oldSpecifiedEnumType = this.specifiedEnumType; + this.specifiedEnumType = newSpecifiedEnumType; + firePropertyChanged(EnumeratedConverter.SPECIFIED_ENUM_TYPE_PROPERTY, oldSpecifiedEnumType, newSpecifiedEnumType); + } + + protected void initialize(XmlConvertibleMapping resourceConvertibleMapping) { + this.resourceConvertibleMapping = resourceConvertibleMapping; + this.specifiedEnumType = this.specifiedEnumType(); + } + + public void update() { + this.setSpecifiedEnumType_(this.specifiedEnumType()); + } + + protected EnumType specifiedEnumType() { + return EnumType.fromOrmResourceModel(this.resourceConvertibleMapping.getEnumerated()); + } + + public TextRange getValidationTextRange() { + return this.resourceConvertibleMapping.getEnumeratedTextRange(); + } + + public void addToResourceModel() { + this.resourceConvertibleMapping.setEnumerated(org.eclipse.jpt.core.resource.orm.EnumType.ORDINAL); + } + + public void removeFromResourceModel() { + this.resourceConvertibleMapping.setEnumerated(null); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java new file mode 100644 index 0000000000..860d5a8f61 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.core.context.GeneratedValue; +import org.eclipse.jpt.core.context.GenerationType; +import org.eclipse.jpt.core.context.Generator; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmGeneratedValue; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.XmlGeneratedValue; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * + */ +public class GenericOrmGeneratedValue + extends AbstractOrmXmlContextNode + implements OrmGeneratedValue +{ + protected XmlGeneratedValue resourceGeneratedValue; + + protected GenerationType specifiedStrategy; + + protected String specifiedGenerator; + protected String defaultGenerator; + + + public GenericOrmGeneratedValue(XmlContextNode parent, XmlGeneratedValue resourceGeneratedValue) { + super(parent); + this.initialize(resourceGeneratedValue); + } + + protected void initialize(XmlGeneratedValue xmlGeneratedValue) { + this.resourceGeneratedValue = xmlGeneratedValue; + this.specifiedStrategy = this.buildStrategy(); + this.specifiedGenerator = xmlGeneratedValue.getGenerator(); + //TODO + this.defaultGenerator = null; + } + + @Override + public XmlContextNode getParent() { + return (XmlContextNode) super.getParent(); + } + + + // ********** strategy ********** + + public GenerationType getStrategy() { + return (this.specifiedStrategy != null) ? this.specifiedStrategy : this.getDefaultStrategy(); + } + + public GenerationType getDefaultStrategy() { + return GeneratedValue.DEFAULT_STRATEGY; + } + + public GenerationType getSpecifiedStrategy() { + return this.specifiedStrategy; + } + + public void setSpecifiedStrategy(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.resourceGeneratedValue.setStrategy(GenerationType.toOrmResourceModel(strategy)); + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + protected void setSpecifiedStrategy_(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + + // ********** generator ********** + + public String getGenerator() { + return (this.specifiedGenerator != null) ? this.specifiedGenerator : this.defaultGenerator; + } + + public String getDefaultGenerator() { + return this.defaultGenerator; + } + + protected void setDefaultGenerator(String generator) { + String old = this.defaultGenerator; + this.defaultGenerator = generator; + this.firePropertyChanged(DEFAULT_GENERATOR_PROPERTY, old, generator); + } + + public String getSpecifiedGenerator() { + return this.specifiedGenerator; + } + + public void setSpecifiedGenerator(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.resourceGeneratedValue.setGenerator(generator); + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + protected void setSpecifiedGenerator_(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + + // ********** text ranges ********** + + public TextRange getValidationTextRange() { + TextRange validationTextRange = this.resourceGeneratedValue.getValidationTextRange(); + return validationTextRange != null ? validationTextRange : getParent().getValidationTextRange(); + } + + public TextRange getGeneratorTextRange() { + TextRange textRange = this.resourceGeneratedValue.getGeneratorTextRange(); + return textRange != null ? textRange : getValidationTextRange(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + String generator = this.getGenerator(); + if (generator == null) { + return; + } + + for (Iterator<Generator> stream = this.getPersistenceUnit().generators(); stream.hasNext(); ) { + if (generator.equals(stream.next().getName())) { + return; + } + } + + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME, + new String[] {generator}, + this.getParent(), + this.getGeneratorTextRange() + ) + ); + } + + + // ********** update from resource model ********** + + public void update(XmlGeneratedValue xmlGeneratedValue) { + this.resourceGeneratedValue = xmlGeneratedValue; + this.setSpecifiedStrategy_(this.buildStrategy()); + this.setSpecifiedGenerator_(xmlGeneratedValue.getGenerator()); + //TODO + this.setDefaultGenerator(null); + } + + protected GenerationType buildStrategy() { + return GenerationType.fromOrmResourceModel(this.resourceGeneratedValue.getStrategy()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java new file mode 100644 index 0000000000..2ec03ec9a1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.core.context.Generator; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmGenerator; +import org.eclipse.jpt.core.context.orm.OrmGeneratorContainer; +import org.eclipse.jpt.core.context.orm.OrmSequenceGenerator; +import org.eclipse.jpt.core.context.orm.OrmTableGenerator; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlGeneratorContainer; +import org.eclipse.jpt.core.resource.orm.XmlSequenceGenerator; +import org.eclipse.jpt.core.resource.orm.XmlTableGenerator; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmGeneratorContainer extends AbstractOrmXmlContextNode + implements OrmGeneratorContainer +{ + protected OrmSequenceGenerator sequenceGenerator; + + protected OrmTableGenerator tableGenerator; + + protected final XmlGeneratorContainer resourceGeneratorContainer; + + public GenericOrmGeneratorContainer(XmlContextNode parent, XmlGeneratorContainer resourceGeneratorContainer) { + super(parent); + this.resourceGeneratorContainer = resourceGeneratorContainer; + this.initializeSequenceGenerator(); + this.initializeTableGenerator(); + } + + public OrmSequenceGenerator addSequenceGenerator() { + if (getSequenceGenerator() != null) { + throw new IllegalStateException("sequenceGenerator already exists"); //$NON-NLS-1$ + } + XmlSequenceGenerator resourceSequenceGenerator = buildResourceSequenceGenerator(); + this.sequenceGenerator = buildSequenceGenerator(resourceSequenceGenerator); + this.resourceGeneratorContainer.setSequenceGenerator(resourceSequenceGenerator); + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, null, this.sequenceGenerator); + return this.sequenceGenerator; + } + + public void removeSequenceGenerator() { + if (getSequenceGenerator() == null) { + throw new IllegalStateException("sequenceGenerator does not exist, cannot be removed"); //$NON-NLS-1$ + } + OrmSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; + this.sequenceGenerator = null; + this.resourceGeneratorContainer.setSequenceGenerator(null); + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, oldSequenceGenerator, null); + } + + public OrmSequenceGenerator getSequenceGenerator() { + return this.sequenceGenerator; + } + + protected void setSequenceGenerator(OrmSequenceGenerator newSequenceGenerator) { + OrmSequenceGenerator oldSequenceGenerator = this.sequenceGenerator; + this.sequenceGenerator = newSequenceGenerator; + firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, oldSequenceGenerator, newSequenceGenerator); + } + + public OrmTableGenerator addTableGenerator() { + if (getTableGenerator() != null) { + throw new IllegalStateException("tableGenerator already exists"); //$NON-NLS-1$ + } + XmlTableGenerator resourceTableGenerator = buildResourceTableGenerator(); + this.tableGenerator = buildTableGenerator(resourceTableGenerator); + this.resourceGeneratorContainer.setTableGenerator(resourceTableGenerator); + firePropertyChanged(TABLE_GENERATOR_PROPERTY, null, this.tableGenerator); + return this.tableGenerator; + } + + public void removeTableGenerator() { + if (getTableGenerator() == null) { + throw new IllegalStateException("tableGenerator does not exist, cannot be removed"); //$NON-NLS-1$ + } + OrmTableGenerator oldTableGenerator = this.tableGenerator; + this.tableGenerator = null; + this.resourceGeneratorContainer.setTableGenerator(null); + firePropertyChanged(TABLE_GENERATOR_PROPERTY, oldTableGenerator, null); + } + + public OrmTableGenerator getTableGenerator() { + return this.tableGenerator; + } + + protected void setTableGenerator(OrmTableGenerator newTableGenerator) { + OrmTableGenerator oldTableGenerator = this.tableGenerator; + this.tableGenerator = newTableGenerator; + firePropertyChanged(TABLE_GENERATOR_PROPERTY, oldTableGenerator, newTableGenerator); + } + + protected void initializeSequenceGenerator() { + if (this.resourceGeneratorContainer.getSequenceGenerator() != null) { + this.sequenceGenerator = buildSequenceGenerator(this.resourceGeneratorContainer.getSequenceGenerator()); + } + } + + protected XmlSequenceGenerator buildResourceSequenceGenerator() { + return OrmFactory.eINSTANCE.createXmlSequenceGenerator(); + } + + protected OrmSequenceGenerator buildSequenceGenerator(XmlSequenceGenerator resourceSequenceGenerator) { + return getXmlContextNodeFactory().buildOrmSequenceGenerator(this, resourceSequenceGenerator); + } + + protected void initializeTableGenerator() { + if (this.resourceGeneratorContainer.getTableGenerator() != null) { + this.tableGenerator = buildTableGenerator(this.resourceGeneratorContainer.getTableGenerator()); + } + } + + protected XmlTableGenerator buildResourceTableGenerator() { + return OrmFactory.eINSTANCE.createXmlTableGenerator(); + } + + protected OrmTableGenerator buildTableGenerator(XmlTableGenerator resourceTableGenerator) { + return getXmlContextNodeFactory().buildOrmTableGenerator(this, resourceTableGenerator); + } + + public void update() { + this.updateSequenceGenerator(); + this.updateTableGenerator(); + } + + protected void updateSequenceGenerator() { + if (this.resourceGeneratorContainer.getSequenceGenerator() == null) { + if (getSequenceGenerator() != null) { + setSequenceGenerator(null); + } + } + else { + if (getSequenceGenerator() == null) { + setSequenceGenerator(buildSequenceGenerator(this.resourceGeneratorContainer.getSequenceGenerator())); + } + else { + getSequenceGenerator().update(this.resourceGeneratorContainer.getSequenceGenerator()); + } + } + } + + protected void updateTableGenerator() { + if (this.resourceGeneratorContainer.getTableGenerator() == null) { + if (getTableGenerator() != null) { + setTableGenerator(null); + } + } + else { + if (getTableGenerator() == null) { + setTableGenerator(buildTableGenerator(this.resourceGeneratorContainer.getTableGenerator())); + } + else { + getTableGenerator().update(this.resourceGeneratorContainer.getTableGenerator()); + } + } + } + + // **************** validation ********************************************* + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateGenerators(messages); + } + + protected void validateGenerators(List<IMessage> messages) { + for (Iterator<OrmGenerator> localGenerators = this.generators(); localGenerators.hasNext(); ) { + OrmGenerator localGenerator = localGenerators.next(); + for (Iterator<Generator> globalGenerators = this.getPersistenceUnit().generators(); globalGenerators.hasNext(); ) { + if (localGenerator.duplicates(globalGenerators.next())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_DUPLICATE_NAME, + new String[] {localGenerator.getName()}, + localGenerator, + localGenerator.getNameTextRange() + ) + ); + } + } + } + } + + protected Iterator<OrmGenerator> generators() { + ArrayList<OrmGenerator> generators = new ArrayList<OrmGenerator>(); + this.addGeneratorsTo(generators); + return generators.iterator(); + } + + protected void addGeneratorsTo(ArrayList<OrmGenerator> generators) { + if (this.sequenceGenerator != null) { + generators.add(this.sequenceGenerator); + } + if (this.tableGenerator != null) { + generators.add(this.tableGenerator); + } + } + + public TextRange getValidationTextRange() { + return this.resourceGeneratorContainer.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmIdMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmIdMapping.java new file mode 100644 index 0000000000..7675b12575 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmIdMapping.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmIdMapping; +import org.eclipse.jpt.core.resource.orm.XmlId; + +public class GenericOrmIdMapping extends AbstractOrmIdMapping<XmlId> +{ + + public GenericOrmIdMapping(OrmPersistentAttribute parent, XmlId resourceMapping) { + super(parent, resourceMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java new file mode 100644 index 0000000000..c9b27ba0c0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; + +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmBaseColumn; +import org.eclipse.jpt.core.resource.orm.XmlJoinColumn; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class GenericOrmJoinColumn extends AbstractOrmBaseColumn<XmlJoinColumn> implements OrmJoinColumn +{ + + protected String specifiedReferencedColumnName; + + protected String defaultReferencedColumnName; + + protected XmlJoinColumn resourceJoinColumn; + + public GenericOrmJoinColumn(XmlContextNode parent, OrmJoinColumn.Owner owner, XmlJoinColumn resourceJoinColumn) { + super(parent, owner); + this.initialize(resourceJoinColumn); + } + + public void initializeFrom(JoinColumn oldColumn) { + super.initializeFrom(oldColumn); + setSpecifiedReferencedColumnName(oldColumn.getSpecifiedReferencedColumnName()); + } + + public String getReferencedColumnName() { + return (this.getSpecifiedReferencedColumnName() == null) ? getDefaultReferencedColumnName() : this.getSpecifiedReferencedColumnName(); + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + getResourceColumn().setReferencedColumnName(newSpecifiedReferencedColumnName); + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + protected void setSpecifiedReferencedColumnName_(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String newDefaultReferencedColumnName) { + String oldDefaultReferencedColumnName = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = newDefaultReferencedColumnName; + firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, oldDefaultReferencedColumnName, newDefaultReferencedColumnName); + } + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + @Override + public OrmJoinColumn.Owner getOwner() { + return (OrmJoinColumn.Owner) this.owner; + } + + public Table getReferencedColumnDbTable() { + return getOwner().getReferencedColumnDbTable(); + } + + public Column getReferencedDbColumn() { + Table table = getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(getReferencedColumnName()); + } + + public boolean isReferencedColumnResolved() { + return getReferencedDbColumn() != null; + } + + public TextRange getReferencedColumnNameTextRange() { + if (getResourceColumn() != null) { + TextRange textRange = getResourceColumn().getReferencedColumnNameTextRange(); + if (textRange != null) { + return textRange; + } + } + return getOwner().getValidationTextRange(); + } + + + @Override + protected XmlJoinColumn getResourceColumn() { + return this.resourceJoinColumn; + } + + @Override + protected void addResourceColumn() { + //joinColumns are part of a collection, the join-column element will be removed/added + //when the XmlJoinColumn is removed/added to the XmlEntity collection + } + + @Override + protected void removeResourceColumn() { + //joinColumns are part of a collection, the pk-join-column element will be removed/added + //when the XmlJoinColumn is removed/added to the XmlEntity collection + } + + + @Override + protected void initialize(XmlJoinColumn xjc) { + this.resourceJoinColumn = xjc; + super.initialize(xjc); + this.specifiedReferencedColumnName = buildSpecifiedReferencedColumnName(xjc); + this.defaultReferencedColumnName = buildDefaultReferencedColumnName(); + } + + @Override + public void update(XmlJoinColumn xjc) { + this.resourceJoinColumn = xjc; + super.update(xjc); + this.setSpecifiedReferencedColumnName_(buildSpecifiedReferencedColumnName(xjc)); + this.setDefaultReferencedColumnName(buildDefaultReferencedColumnName()); + } + + protected String buildSpecifiedReferencedColumnName(XmlJoinColumn xjc) { + return (xjc == null) ? null : xjc.getReferencedColumnName(); + } + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.getOwner()); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.getOwner()); + } + + + //******************* validation *********************** + + @Override + //this method will only be called if the table validates correctly + protected void validateName(List<IMessage> messages) { + //do not call super here, first need to check for multiple join columns errors + this.validateJoinColumnName(messages); + this.validateReferencedColumnName(messages); + } + + protected void validateJoinColumnName(List<IMessage> messages) { + if (this.getSpecifiedName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedNameMultipleJoinColumnsMessage()); + } + else if (this.getName() != null){ + super.validateName(messages); + } + //If the name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected void validateReferencedColumnName(List<IMessage> messages) { + if (this.getSpecifiedReferencedColumnName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage()); + } + else if (this.getSpecifiedReferencedColumnName() != null) { + Table refColumnDbTable = this.getReferencedColumnDbTable(); + if (refColumnDbTable != null && ! this.isReferencedColumnResolved()) { + messages.add(getOwner().buildUnresolvedReferencedColumnNameMessage(this, this.getReferencedColumnNameTextRange())); + } + } + //If the referenced column name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(this, getNameTextRange()); + } + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(this, getReferencedColumnNameTextRange()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java new file mode 100644 index 0000000000..4f5d33555b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmJoinTable.java @@ -0,0 +1,766 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jpt.core.context.BaseColumn; +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.JoinTable; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.PersistentAttribute; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmJoinTable; +import org.eclipse.jpt.core.context.orm.OrmJoinTableJoiningStrategy; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationDescriptionMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.AbstractXmlReferenceTable; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlJoinColumn; +import org.eclipse.jpt.core.resource.orm.XmlJoinTable; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * orm.xml join table + */ +public class GenericOrmJoinTable + extends GenericOrmReferenceTable + implements OrmJoinTable +{ + + protected OrmJoinColumn defaultInverseJoinColumn; + + protected final Vector<OrmJoinColumn> specifiedInverseJoinColumns = new Vector<OrmJoinColumn>(); + protected final OrmJoinColumn.Owner inverseJoinColumnOwner; + + + public GenericOrmJoinTable(OrmJoinTableJoiningStrategy parent, XmlJoinTable resourceJoinTable) { + super(parent); + this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner(); + this.initialize(resourceJoinTable); + } + + @Override + protected OrmJoinColumn.Owner buildJoinColumnOwner() { + return new JoinColumnOwner(); + } + + protected OrmJoinColumn.Owner buildInverseJoinColumnOwner() { + return new InverseJoinColumnOwner(); + } + + public RelationshipMapping getRelationshipMapping() { + return getParent().getRelationshipReference().getRelationshipMapping(); + } + + public void initializeFrom(JoinTable oldJoinTable) { + super.initializeFrom(oldJoinTable); + for (Iterator<OrmJoinColumn> stream = oldJoinTable.specifiedInverseJoinColumns(); stream.hasNext(); ) { + this.addSpecifiedInverseJoinColumnFrom(stream.next()); + } + } + + protected void initialize(XmlJoinTable joinTable) { + super.initialize(joinTable); + this.initializeSpecifiedInverseJoinColumns(joinTable); + this.initializeDefaultInverseJoinColumn(); + } + + @Override + protected void update(AbstractXmlReferenceTable joinTable) { + super.update(joinTable); + this.updateSpecifiedInverseJoinColumns((XmlJoinTable) joinTable); + this.updateDefaultInverseJoinColumn(); + } + + public PersistentAttribute getPersistentAttribute() { + return getRelationshipMapping().getPersistentAttribute(); + } + + + // ********** AbstractOrmTable implementation ********** + + @Override + public OrmJoinTableJoiningStrategy getParent() { + return (OrmJoinTableJoiningStrategy) super.getParent(); + } + + @Override + protected String buildDefaultName() { + return this.getParent().getJoinTableDefaultName(); + } + + @Override + protected XmlJoinTable getResourceTable() { + return this.getParent().getResourceJoinTable(); + } + + @Override + protected XmlJoinTable addResourceTable() { + return getParent().addResourceJoinTable(); + } + + @Override + protected void removeResourceTable() { + getParent().removeResourceJoinTable(); + } + + + // ********** inverse join columns ********** + + public ListIterator<OrmJoinColumn> inverseJoinColumns() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumns() : this.defaultInverseJoinColumns(); + } + + public int inverseJoinColumnsSize() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumnsSize() : this.defaultInverseJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedInverseJoinColumn() { + MappingTools.convertJoinTableDefaultToSpecifiedInverseJoinColumn(this); + } + + + // ********** default inverse join column ********** + + public OrmJoinColumn getDefaultInverseJoinColumn() { + return this.defaultInverseJoinColumn; + } + + protected void setDefaultInverseJoinColumn(OrmJoinColumn defaultInverseJoinColumn) { + OrmJoinColumn old = this.defaultInverseJoinColumn; + this.defaultInverseJoinColumn = defaultInverseJoinColumn; + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, old, defaultInverseJoinColumn); + } + + protected ListIterator<OrmJoinColumn> defaultInverseJoinColumns() { + if (this.defaultInverseJoinColumn != null) { + return new SingleElementListIterator<OrmJoinColumn>(this.defaultInverseJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultInverseJoinColumnsSize() { + return (this.defaultInverseJoinColumn == null) ? 0 : 1; + } + + protected void initializeDefaultInverseJoinColumn() { + if (this.shouldBuildDefaultInverseJoinColumn()) { + this.defaultInverseJoinColumn = this.buildInverseJoinColumn(null); + } + } + + protected void updateDefaultInverseJoinColumn() { + if (this.shouldBuildDefaultInverseJoinColumn()) { + if (this.defaultInverseJoinColumn == null) { + this.setDefaultInverseJoinColumn(this.buildInverseJoinColumn(null)); + } else { + this.defaultInverseJoinColumn.update(null); + } + } else { + this.setDefaultInverseJoinColumn(null); + } + } + + protected boolean shouldBuildDefaultInverseJoinColumn() { + return ! this.hasSpecifiedInverseJoinColumns(); + } + + + // ********** specified inverse join columns ********** + + public ListIterator<OrmJoinColumn> specifiedInverseJoinColumns() { + return new CloneListIterator<OrmJoinColumn>(this.specifiedInverseJoinColumns); + } + + public int specifiedInverseJoinColumnsSize() { + return this.specifiedInverseJoinColumns.size(); + } + + public boolean hasSpecifiedInverseJoinColumns() { + return !this.specifiedInverseJoinColumns.isEmpty(); + } + + protected void addSpecifiedInverseJoinColumnFrom(OrmJoinColumn oldJoinColumn) { + OrmJoinColumn newJoinColumn = this.addSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.size()); + newJoinColumn.initializeFrom(oldJoinColumn); + } + + public OrmJoinColumn addSpecifiedInverseJoinColumn(int index) { + if (this.getResourceTable() == null) { + this.addResourceTable(); + } + XmlJoinColumn xmlJoinColumn = OrmFactory.eINSTANCE.createXmlJoinColumn(); + OrmJoinColumn joinColumn = this.buildInverseJoinColumn(xmlJoinColumn); + this.specifiedInverseJoinColumns.add(index, joinColumn); + this.getResourceTable().getInverseJoinColumns().add(index, xmlJoinColumn); + this.fireItemAdded(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, index, joinColumn); + return joinColumn; + } + + protected void addSpecifiedInverseJoinColumn(int index, OrmJoinColumn joinColumn) { + this.addItemToList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedInverseJoinColumn(OrmJoinColumn joinColumn) { + this.addSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.size(), joinColumn); + } + + public void removeSpecifiedInverseJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedInverseJoinColumn(int index) { + OrmJoinColumn removedJoinColumn = this.specifiedInverseJoinColumns.remove(index); + if ( ! this.hasSpecifiedInverseJoinColumns()) { + //create the defaultInverseJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultInverseJoinColumn = this.buildInverseJoinColumn(null); + } + this.getResourceTable().getInverseJoinColumns().remove(index); + this.fireItemRemoved(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, index, removedJoinColumn); + if (this.defaultInverseJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, null, this.defaultInverseJoinColumn); + } + } + + protected void removeSpecifiedInverseJoinColumn_(OrmJoinColumn joinColumn) { + this.removeItemFromList(joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedInverseJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedInverseJoinColumns, targetIndex, sourceIndex); + this.getResourceTable().getInverseJoinColumns().move(targetIndex, sourceIndex); + this.fireItemMoved(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + public void clearSpecifiedInverseJoinColumns() { + this.specifiedInverseJoinColumns.clear(); + this.defaultInverseJoinColumn = this.buildInverseJoinColumn(null); + this.getResourceTable().getInverseJoinColumns().clear(); + this.fireListCleared(SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, null, this.defaultInverseJoinColumn); + } + + protected OrmJoinColumn buildInverseJoinColumn(XmlJoinColumn resourceJoinColumn) { + return this.buildJoinColumn(resourceJoinColumn, this.inverseJoinColumnOwner); + } + + protected void initializeSpecifiedInverseJoinColumns(XmlJoinTable xmlJoinTable) { + if (xmlJoinTable != null) { + for (XmlJoinColumn xmlJoinColumn : xmlJoinTable.getInverseJoinColumns()) { + this.specifiedInverseJoinColumns.add(this.buildInverseJoinColumn(xmlJoinColumn)); + } + } + } + + protected void updateSpecifiedInverseJoinColumns(XmlJoinTable xmlJoinTable) { + Iterator<XmlJoinColumn> xmlJoinColumns = this.xmlInverseJoinColumns(xmlJoinTable); + + for (ListIterator<OrmJoinColumn> contextJoinColumns = this.specifiedInverseJoinColumns(); contextJoinColumns.hasNext(); ) { + OrmJoinColumn contextColumn = contextJoinColumns.next(); + if (xmlJoinColumns.hasNext()) { + contextColumn.update(xmlJoinColumns.next()); + } else { + this.removeSpecifiedInverseJoinColumn_(contextColumn); + } + } + + while (xmlJoinColumns.hasNext()) { + this.addSpecifiedInverseJoinColumn(this.buildInverseJoinColumn(xmlJoinColumns.next())); + } + } + + protected Iterator<XmlJoinColumn> xmlInverseJoinColumns(XmlJoinTable xmlJoinTable) { + // make a copy of the XML join columns (to prevent ConcurrentModificationException) + return (xmlJoinTable == null) ? EmptyIterator.<XmlJoinColumn>instance() + : new CloneIterator<XmlJoinColumn>(xmlJoinTable.getInverseJoinColumns()); + } + + + // ********** validation ********** + + @Override + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter) { + super.validateJoinColumns(messages, reporter); + this.validateJoinColumns(this.inverseJoinColumns(), messages, reporter); + } + + @Override + protected boolean shouldValidateAgainstDatabase() { + return getParent().shouldValidateAgainstDatabase(); + } + + @Override + protected String getUnresolvedCatalogMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getUnresolvedNameMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME; + } + + @Override + protected String getUnresolvedSchemaMessageId() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getVirtualAttributeUnresolvedCatalogMessageId() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessageId() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedSchemaMessageId() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA; + } + + // ********** join column owner adapters ********** + + /** + * just a little common behavior + */ + protected abstract class AbstractJoinColumnOwner + implements OrmJoinColumn.Owner + { + protected AbstractJoinColumnOwner() { + super(); + } + + public TypeMapping getTypeMapping() { + return GenericOrmJoinTable.this.getParent().getRelationshipReference().getTypeMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return GenericOrmJoinTable.this.getRelationshipMapping().getPersistentAttribute(); + } + + /** + * If there is a specified table name it needs to be the same + * the default table name. the table is always the join table + */ + public boolean tableNameIsInvalid(String tableName) { + return !StringTools.stringsAreEqual(getDefaultTableName(), tableName); + } + + /** + * the join column can only be on the join table itself + */ + public boolean tableIsAllowed() { + return false; + } + + public Iterator<String> candidateTableNames() { + return EmptyIterator.instance(); + } + + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + String joinTableName = GenericOrmJoinTable.this.getName(); + return (joinTableName == null) ? null : (joinTableName.equals(tableName)) ? GenericOrmJoinTable.this.getDbTable() : null; + } + + /** + * by default, the join column is, obviously, in the join table; + * not sure whether it can be anywhere else... + */ + public String getDefaultTableName() { + return GenericOrmJoinTable.this.getName(); + } + + public TextRange getValidationTextRange() { + return GenericOrmJoinTable.this.getValidationTextRange(); + } + + protected boolean isPersistentAttributeVirtual() { + return getPersistentAttribute().isVirtual(); + } + + protected String getPersistentAttributeName() { + return getPersistentAttribute().getName(); + } + + public IMessage buildTableNotValidMessage(BaseColumn column, TextRange textRange) { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualTableNotValidMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getTableNotValidMessage(), + new String[] { + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.DOES_NOT_MATCH_JOIN_TABLE}, + column, + textRange + ); + } + + protected IMessage buildVirtualTableNotValidMessage(BaseColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualTableNotValidMessage(), + new String[] { + getName(), + column.getTable(), + column.getName(), + JpaValidationDescriptionMessages.DOES_NOT_MATCH_JOIN_TABLE}, + column, + textRange + ); + } + + protected abstract String getTableNotValidMessage(); + + protected abstract String getVirtualTableNotValidMessage(); + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualUnresolvedNameMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedNameMessage(), + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualUnresolvedNameMessage(), + new String[] {getPersistentAttributeName(), column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected abstract String getUnresolvedNameMessage(); + + protected abstract String getVirtualUnresolvedNameMessage(); + + public IMessage buildUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualUnresolvedReferencedColumnNameMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getUnresolvedReferencedColumnNameMessage(), + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualUnresolvedReferencedColumnNameMessage(), + new String[] {this.getPersistentAttributeName(), column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected abstract String getUnresolvedReferencedColumnNameMessage(); + + protected abstract String getVirtualUnresolvedReferencedColumnNameMessage(); + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + if (this.isPersistentAttributeVirtual()) { + return this.buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getUnspecifiedNameMultipleJoinColumnsMessage(), + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getVirtualUnspecifiedNameMultipleJoinColumnsMessage(), + new String[] {this.getPersistentAttributeName()}, + column, + textRange + ); + } + + protected abstract String getUnspecifiedNameMultipleJoinColumnsMessage(); + + protected abstract String getVirtualUnspecifiedNameMultipleJoinColumnsMessage(); + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + if (this.isPersistentAttributeVirtual()) { + return this.buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[] {this.getPersistentAttributeName()}, + column, + textRange + ); + } + + protected abstract String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + + protected abstract String getVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + + /** + * owner for "back-pointer" JoinColumns; + * these point at the source/owning entity + */ + protected class JoinColumnOwner + extends AbstractJoinColumnOwner + { + protected JoinColumnOwner() { + super(); + } + + public Entity getRelationshipTarget() { + return GenericOrmJoinTable.this.getParent().getRelationshipReference().getEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericOrmJoinTable.this.getRelationshipMapping(); + if (relationshipMapping == null) { + return null; + } + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity == null) { + return null; + } + for (PersistentAttribute each : CollectionTools.iterable(targetEntity.getPersistentType().allAttributes())) { + if (each.getMapping().isOwnedBy(relationshipMapping)) { + return each.getName(); + } + } + return null; + } + + @Override + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + org.eclipse.jpt.db.Table dbTable = super.getDbTable(tableName); + return (dbTable != null) ? dbTable : this.getTypeMapping().getDbTable(tableName); + } + + public org.eclipse.jpt.db.Table getReferencedColumnDbTable() { + return getTypeMapping().getPrimaryDbTable(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericOrmJoinTable.this.defaultJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + //built in MappingTools.buildJoinColumnDefaultName() + return null; + } + + public int joinColumnsSize() { + return GenericOrmJoinTable.this.joinColumnsSize(); + } + + @Override + protected String getTableNotValidMessage() { + return JpaValidationMessages.JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + public String getVirtualTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + public String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + public String getVirtualUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + public String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getVirtualUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + } + + + /** + * owner for "forward-pointer" JoinColumns; + * these point at the target/inverse entity + */ + protected class InverseJoinColumnOwner + extends AbstractJoinColumnOwner + { + protected InverseJoinColumnOwner() { + super(); + } + + public Entity getRelationshipTarget() { + RelationshipMapping relationshipMapping = GenericOrmJoinTable.this.getRelationshipMapping(); + return relationshipMapping == null ? null : relationshipMapping.getResolvedTargetEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericOrmJoinTable.this.getRelationshipMapping(); + return relationshipMapping == null ? null : relationshipMapping.getName(); + } + + @Override + public org.eclipse.jpt.db.Table getDbTable(String tableName) { + org.eclipse.jpt.db.Table dbTable = super.getDbTable(tableName); + if (dbTable != null) { + return dbTable; + } + Entity relationshipTarget = this.getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.getDbTable(tableName); + } + + public org.eclipse.jpt.db.Table getReferencedColumnDbTable() { + Entity relationshipTarget = this.getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.getPrimaryDbTable(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericOrmJoinTable.this.defaultInverseJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + //built in MappingTools.buildJoinColumnDefaultName() + return null; + } + + public int joinColumnsSize() { + return GenericOrmJoinTable.this.inverseJoinColumnsSize(); + } + + @Override + protected String getTableNotValidMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + public String getVirtualTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + public String getUnresolvedNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + public String getVirtualUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + public String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + public String getVirtualUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + public String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getVirtualUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + public String getVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmLobConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmLobConverter.java new file mode 100644 index 0000000000..771057930f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmLobConverter.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.LobConverter; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmConverter; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlConvertibleMapping; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericOrmLobConverter extends AbstractOrmXmlContextNode + implements LobConverter, OrmConverter +{ + protected XmlConvertibleMapping resourceConvertibleMapping; + + public GenericOrmLobConverter(OrmAttributeMapping parent, XmlConvertibleMapping resourceMapping) { + super(parent); + this.initialize(resourceMapping); + } + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.LOB_CONVERTER; + } + + public void initialize(XmlConvertibleMapping resourceConvertibleMapping) { + this.resourceConvertibleMapping = resourceConvertibleMapping; + } + + public void update() { + //do nothing + } + + public TextRange getValidationTextRange() { + return this.resourceConvertibleMapping.getLobTextRange(); + } + + public void addToResourceModel() { + this.resourceConvertibleMapping.setLob(true); + } + + public void removeFromResourceModel() { + this.resourceConvertibleMapping.setLob(false); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java new file mode 100644 index 0000000000..517a92c340 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmManyToManyMapping; +import org.eclipse.jpt.core.resource.orm.XmlManyToMany; + +public class GenericOrmManyToManyMapping + extends AbstractOrmManyToManyMapping<XmlManyToMany> +{ + public GenericOrmManyToManyMapping(OrmPersistentAttribute parent, XmlManyToMany resourceMapping) { + super(parent, resourceMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java new file mode 100644 index 0000000000..be6988b905 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmManyToOneMapping; +import org.eclipse.jpt.core.internal.context.orm.GenericOrmManyToOneRelationshipReference; +import org.eclipse.jpt.core.jpa2.context.orm.OrmManyToOneRelationshipReference2_0; +import org.eclipse.jpt.core.resource.orm.XmlManyToOne; + +public class GenericOrmManyToOneMapping + extends AbstractOrmManyToOneMapping<XmlManyToOne> +{ + public GenericOrmManyToOneMapping(OrmPersistentAttribute parent, XmlManyToOne resourceMapping) { + super(parent, resourceMapping); + } + + @Override + protected OrmManyToOneRelationshipReference2_0 buildRelationshipReference() { + return new GenericOrmManyToOneRelationshipReference(this, this.resourceAttributeMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java new file mode 100644 index 0000000000..bbb9ea11cf --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmMappedSuperclass; +import org.eclipse.jpt.core.resource.orm.XmlMappedSuperclass; + + +public class GenericOrmMappedSuperclass extends AbstractOrmMappedSuperclass +{ + + public GenericOrmMappedSuperclass(OrmPersistentType parent, XmlMappedSuperclass resourceMapping) { + super(parent, resourceMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java new file mode 100644 index 0000000000..43fa8e2a73 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.NamedNativeQuery; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmNamedNativeQuery; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmQuery; +import org.eclipse.jpt.core.resource.orm.XmlNamedNativeQuery; + + +public class GenericOrmNamedNativeQuery extends AbstractOrmQuery<XmlNamedNativeQuery> + implements OrmNamedNativeQuery +{ + + protected String resultClass; + + protected String resultSetMapping; + + + public GenericOrmNamedNativeQuery(XmlContextNode parent, XmlNamedNativeQuery resourceQuery) { + super(parent, resourceQuery); + } + + public char getResultClassEnclosingTypeSeparator() { + return '$'; + } + + public String getResultClass() { + return this.resultClass; + } + + public void setResultClass(String newResultClass) { + String oldResultClass = this.resultClass; + this.resultClass = newResultClass; + getResourceQuery().setResultClass(newResultClass); + firePropertyChanged(NamedNativeQuery.RESULT_CLASS_PROPERTY, oldResultClass, newResultClass); + } + + public String getResultSetMapping() { + return this.resultSetMapping; + } + + public void setResultSetMapping(String newResultSetMapping) { + String oldResultSetMapping = this.resultSetMapping; + this.resultSetMapping = newResultSetMapping; + getResourceQuery().setResultSetMapping(newResultSetMapping); + firePropertyChanged(NamedNativeQuery.RESULT_SET_MAPPING_PROPERTY, oldResultSetMapping, newResultSetMapping); + } + + + @Override + protected void initialize(XmlNamedNativeQuery resourceQuery) { + super.initialize(resourceQuery); + this.resultClass = resourceQuery.getResultClass(); + this.resultSetMapping = resourceQuery.getResultSetMapping(); + } + + @Override + public void update(XmlNamedNativeQuery resourceQuery) { + super.update(resourceQuery); + this.setResultClass(resourceQuery.getResultClass()); + this.setResultSetMapping(resourceQuery.getResultSetMapping()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java new file mode 100644 index 0000000000..94c0693e57 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmNamedQuery; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmQuery; +import org.eclipse.jpt.core.resource.orm.XmlNamedQuery; + + +public class GenericOrmNamedQuery extends AbstractOrmQuery<XmlNamedQuery> implements OrmNamedQuery +{ + + public GenericOrmNamedQuery(XmlContextNode parent, XmlNamedQuery resourceNamedQuery) { + super(parent, resourceNamedQuery); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java new file mode 100644 index 0000000000..90fab75123 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.XmlNullAttributeMapping; + + +public class GenericOrmNullAttributeMapping + extends AbstractOrmAttributeMapping<XmlNullAttributeMapping> +{ + + public GenericOrmNullAttributeMapping(OrmPersistentAttribute parent, XmlNullAttributeMapping resourceMapping) { + super(parent, resourceMapping); + } + + public int getXmlSequence() { + return -1; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmAttributeMapping(this); + } + + public String getKey() { + return null; + } + + public void addToResourceModel(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + public void removeFromResourceModel(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullConverter.java new file mode 100644 index 0000000000..a69d79ac07 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmNullConverter.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmConverter; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericOrmNullConverter extends AbstractOrmXmlContextNode + implements OrmConverter +{ + + public GenericOrmNullConverter(OrmAttributeMapping parent) { + super(parent); + } + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.NO_CONVERTER; + } + + public TextRange getValidationTextRange() { + return null; + } + + public void update() { + // do nothing, null implementation + } + + public void addToResourceModel() { + // do nothing, null implementation + } + + public void removeFromResourceModel() { + // do nothing, null implementation + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java new file mode 100644 index 0000000000..facb180a33 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.context.orm.OrmRelationshipReference; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmOneToManyMapping; +import org.eclipse.jpt.core.resource.orm.XmlOneToMany; + + +public class GenericOrmOneToManyMapping extends AbstractOrmOneToManyMapping<XmlOneToMany> +{ + + public GenericOrmOneToManyMapping(OrmPersistentAttribute parent, XmlOneToMany resourceMapping) { + super(parent, resourceMapping); + } + + @Override + protected OrmRelationshipReference buildRelationshipReference() { + return new GenericOrmOneToManyRelationshipReference(this, this.resourceAttributeMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyRelationshipReference.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyRelationshipReference.java new file mode 100644 index 0000000000..2dc8d15490 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToManyRelationshipReference.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmJoinColumnJoiningStrategy; +import org.eclipse.jpt.core.context.orm.OrmJoiningStrategy; +import org.eclipse.jpt.core.context.orm.OrmOneToManyMapping; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmOneToManyRelationshipReference; +import org.eclipse.jpt.core.resource.orm.XmlOneToMany; + +public class GenericOrmOneToManyRelationshipReference + extends AbstractOrmOneToManyRelationshipReference +{ + + public GenericOrmOneToManyRelationshipReference( + OrmOneToManyMapping parent, XmlOneToMany resource) { + + super(parent, resource); + } + + @Override + protected OrmJoinColumnJoiningStrategy buildJoinColumnJoiningStrategy() { + return new NullOrmJoinColumnJoiningStrategy(this); + } + + + @Override + protected OrmJoiningStrategy calculatePredominantJoiningStrategy() { + if (this.mappedByJoiningStrategy.getMappedByAttribute() != null) { + return this.mappedByJoiningStrategy; + } + return this.joinTableJoiningStrategy; + } + + + // **************** join columns ******************************************* + + @Override + public boolean usesJoinColumnJoiningStrategy() { + return false; + } + + @Override + public void setJoinColumnJoiningStrategy() { + throw new UnsupportedOperationException("join column joining strategy not supported on a 1.0 1-m mapping"); //$NON-NLS-1$ + } + + @Override + public void unsetJoinColumnJoiningStrategy() { + throw new UnsupportedOperationException("join column joining strategy not supported on a 1.0 1-m mapping"); //$NON-NLS-1$ + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java new file mode 100644 index 0000000000..604573441f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmOneToOneMapping; +import org.eclipse.jpt.core.internal.context.orm.GenericOrmOneToOneRelationshipReference; +import org.eclipse.jpt.core.jpa2.context.orm.OrmOneToOneRelationshipReference2_0; +import org.eclipse.jpt.core.resource.orm.XmlOneToOne; + + +public class GenericOrmOneToOneMapping + extends AbstractOrmOneToOneMapping<XmlOneToOne> +{ + + // ********** constructor ********** + public GenericOrmOneToOneMapping(OrmPersistentAttribute parent, XmlOneToOne resourceMapping) { + super(parent, resourceMapping); + } + + @Override + protected OrmOneToOneRelationshipReference2_0 buildRelationshipReference() { + return new GenericOrmOneToOneRelationshipReference(this, this.resourceAttributeMapping); + } +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOrderable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOrderable.java new file mode 100644 index 0000000000..ec57ce6b5f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmOrderable.java @@ -0,0 +1,336 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.Orderable; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmNamedColumn; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.Orderable2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmOrderColumn2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmOrderable2_0; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlOrderColumn; +import org.eclipse.jpt.core.resource.orm.XmlOrderable; +import org.eclipse.jpt.core.resource.orm.v2_0.XmlOrderable_2_0; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * ORM multi-relationship (m:m, 1:m) mapping + */ +public class GenericOrmOrderable + extends AbstractOrmXmlContextNode + implements OrmOrderable2_0 +{ + + protected String specifiedOrderBy; + protected boolean noOrdering = false; + protected boolean pkOrdering = false; + protected boolean customOrdering = false; + + //JPA 2.0 + protected final Orderable.Owner owner; //the owner is only used for 2.0 projects + protected boolean orderColumnOrdering = false; + protected final OrmOrderColumn2_0 orderColumn; + + public GenericOrmOrderable(OrmAttributeMapping parent, Orderable.Owner owner) { + super(parent); + this.owner = owner; + this.orderColumn = getXmlContextNodeFactory().buildOrmOrderColumn(this, new OrderColumnOwner()); + this.initializeOrdering(); + } + + public void update() { + this.updateOrdering(); + } + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + protected OrmPersistentAttribute getPersistentAttribute() { + return getParent().getPersistentAttribute(); + } + + protected XmlOrderable getResourceOrderable() { + return (XmlOrderable) getParent().getResourceAttributeMapping(); + } + + // **************** order by *********************************************** + + public String getSpecifiedOrderBy() { + return this.specifiedOrderBy; + } + + public void setSpecifiedOrderBy(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + this.getResourceOrderable().setOrderBy(orderBy); + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected void setSpecifiedOrderBy_(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected void initializeOrdering() { + this.specifiedOrderBy = this.getXmlOrderBy(); + XmlOrderColumn resourceOrderColumn = getXmlOrderColumn(); + if (this.specifiedOrderBy == null && resourceOrderColumn == null) { + this.noOrdering = true; + } else if (this.specifiedOrderBy != null && this.specifiedOrderBy.equals("")) { //$NON-NLS-1$ + this.pkOrdering = true; + } else if (resourceOrderColumn == null) { + this.customOrdering = true; + } else { + this.orderColumnOrdering = true; + } + } + + protected void updateOrdering() { + this.setSpecifiedOrderBy_(this.getXmlOrderBy()); + XmlOrderColumn resourceOrderColumn = getXmlOrderColumn(); + if (this.specifiedOrderBy == null && resourceOrderColumn == null) { + this.setNoOrdering_(true); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + } else if (this.specifiedOrderBy != null && this.specifiedOrderBy.equals("")) { //$NON-NLS-1$ + this.setNoOrdering_(false); + this.setPkOrdering_(true); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + } else if (resourceOrderColumn == null){ + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(true); + this.setOrderColumnOrdering_(false); + } else { + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(true); + } + this.orderColumn.update(this.getResourceOrderable()); + } + + protected String getXmlOrderBy() { + return this.getResourceOrderable().getOrderBy(); + } + + protected XmlOrderColumn getXmlOrderColumn() { + return ((XmlOrderable_2_0) this.getResourceOrderable()).getOrderColumn(); + } + + // **************** no ordering *********************************************** + + public boolean isNoOrdering() { + return this.noOrdering; + } + + public void setNoOrdering(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + if (noOrdering) { + this.getResourceOrderable().setOrderBy(null); + this.removeXmlOrderColumn(); + } + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + protected void setNoOrdering_(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + + // **************** pk ordering *********************************************** + + public boolean isPkOrdering() { + return this.pkOrdering; + } + + public void setPkOrdering(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + if (pkOrdering) { + this.getResourceOrderable().setOrderBy(""); //$NON-NLS-1$ + this.removeXmlOrderColumn(); + } + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + protected void setPkOrdering_(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + + // **************** custom ordering *********************************************** + + public boolean isCustomOrdering() { + return this.customOrdering; + } + + public void setCustomOrdering(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + if (customOrdering) { + this.setSpecifiedOrderBy(""); //$NON-NLS-1$ + this.removeXmlOrderColumn(); + } + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + protected void setCustomOrdering_(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + // ********** Orderable2_0 implementation ********** + // **************** order column ordering *********************************************** + + public boolean isOrderColumnOrdering() { + return this.orderColumnOrdering; + } + + public void setOrderColumnOrdering(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + if (orderColumnOrdering) { + this.getResourceOrderable().setOrderBy(null); + addXmlOrderColumn(); + } + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + protected void setOrderColumnOrdering_(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + public OrmOrderColumn2_0 getOrderColumn() { + return this.orderColumn; + } + + protected void addXmlOrderColumn() { + ((XmlOrderable_2_0) getResourceOrderable()).setOrderColumn(OrmFactory.eINSTANCE.createXmlOrderColumn()); + } + + protected void removeXmlOrderColumn() { + ((XmlOrderable_2_0) getResourceOrderable()).setOrderColumn(null); + } + + public String getDefaultTableName() { + return getOwner().getTableName(); + } + + /** + * Only call this for 2.0 projects + */ + protected Orderable2_0.Owner getOwner() { + return (Orderable2_0.Owner) this.owner; + } + + + // ********** Validation ********** + + public TextRange getValidationTextRange() { + TextRange textRange = getResourceOrderable().getValidationTextRange(); + return (textRange != null) ? textRange : this.getParent().getValidationTextRange(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + //order-column and order-by both specified is handled with schema validation + if (isOrderColumnOrdering()) { + //TODO validation message if type is not List + this.getOrderColumn().validate(messages, reporter); + } + } + + public String getUnresolvedNameMessage() { + return JpaValidationMessages.ORDER_COLUMN_UNRESOLVED_NAME; + } + + + // ********** OrmNamedColumn implementation ********** + + protected class OrderColumnOwner implements OrmNamedColumn.Owner { + + public String getDefaultTableName() { + return GenericOrmOrderable.this.getDefaultTableName(); + } + + public Table getDbTable(String tableName) { + return getOwner().getDbTable(tableName); + } + + public String getDefaultColumnName() { + return getPersistentAttribute().getName() + "_ORDER"; //$NON-NLS-1$ + } + + public TypeMapping getTypeMapping() { + return getPersistentAttribute().getOwningTypeMapping(); + } + + public TextRange getValidationTextRange() { + return GenericOrmOrderable.this.getValidationTextRange(); + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualUnresolvedNameMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ORDER_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ATTRIBUTE_ORDER_COLUMN_UNRESOLVED_NAME, + new String[] {getPersistentAttributeName(), column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + protected boolean isPersistentAttributeVirtual() { + return getPersistentAttribute().isVirtual(); + } + + protected String getPersistentAttributeName() { + return getPersistentAttribute().getName(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.java new file mode 100644 index 0000000000..076d2c428c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; + +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmPersistentAttribute; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.XmlAttributeMapping; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + + +public class GenericOrmPersistentAttribute extends AbstractOrmPersistentAttribute +{ + + public GenericOrmPersistentAttribute(OrmPersistentType parent, Owner owner, XmlAttributeMapping resourceMapping) { + super(parent, owner, resourceMapping); + } + + //****************** AccessHolder implementation ******************* + + /** + * GenericOrmPersistentAttribute does not support specified access (no access element in 1.0), so we return null + */ + public AccessType getSpecifiedAccess() { + return null; + } + + public void setSpecifiedAccess(AccessType newSpecifiedAccess) { + throw new UnsupportedOperationException("specifiedAccess is not supported for GenericOrmPersistentAttribute"); //$NON-NLS-1$ + } + + @Override + protected void validateAttribute(List<IMessage> messages) { + super.validateAttribute(messages); + if (this.javaPersistentAttribute != null) { + JavaPersistentType javaPersistentType = getOwningPersistentType().getJavaPersistentType(); + if (javaPersistentType != null && javaPersistentType.getAttributeNamed(this.javaPersistentAttribute.getName()) == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENT_ATTRIBUTE_INHERITED_ATTRIBUTES_NOT_SUPPORTED, + new String[] {this.getName(), this.getOwningPersistentType().getMapping().getClass_()}, + this.attributeMapping, + this.attributeMapping.getNameTextRange() + ) + ); + } + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java new file mode 100644 index 0000000000..cf52e6c52a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPersistentType.java @@ -0,0 +1,1080 @@ +/******************************************************************************* + * Copyright (c) 2006, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Vector; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.PersistentAttribute; +import org.eclipse.jpt.core.context.PersistentType; +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.orm.EntityMappings; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmAttributeMappingDefinition; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.context.orm.OrmStructureNodes; +import org.eclipse.jpt.core.context.orm.OrmTypeMapping; +import org.eclipse.jpt.core.context.orm.OrmTypeMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.JpaFactory2_0; +import org.eclipse.jpt.core.jpa2.context.MetamodelSourceType; +import org.eclipse.jpt.core.jpa2.context.java.JavaPersistentType2_0; +import org.eclipse.jpt.core.jpa2.context.orm.OrmPersistentType2_0; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.OrmPackage; +import org.eclipse.jpt.core.resource.orm.XmlAttributeMapping; +import org.eclipse.jpt.core.resource.orm.XmlTypeMapping; +import org.eclipse.jpt.core.resource.xml.EmfTools; +import org.eclipse.jpt.core.utility.BodySourceWriter; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.ClassName; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.Tools; +import org.eclipse.jpt.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.utility.internal.iterators.ChainIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.utility.internal.iterators.TransformationIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * ORM persistent type:<ul> + * <li>mapping + * <li>access + * <li>attributes + * <li>super persistent type + * <li>Java persistent type + * </ul> + */ +public class GenericOrmPersistentType + extends AbstractOrmXmlContextNode + implements OrmPersistentType2_0 +{ + protected OrmTypeMapping mapping; + + protected AccessType defaultAccess; + + protected AccessType specifiedAccess; + + protected final Vector<OrmPersistentAttribute> specifiedAttributes = new Vector<OrmPersistentAttribute>(); + + protected final Vector<OrmPersistentAttribute> virtualAttributes = new Vector<OrmPersistentAttribute>(); + + protected PersistentType superPersistentType; + + protected String declaringTypeName; + + protected JavaPersistentType javaPersistentType; + + protected final MetamodelSourceType.Synchronizer metamodelSynchronizer; + + + public GenericOrmPersistentType(EntityMappings parent, XmlTypeMapping resourceMapping) { + super(parent); + this.mapping = this.buildMapping(resourceMapping); + this.specifiedAccess = this.buildSpecifiedAccess(); + this.defaultAccess = this.buildDefaultAccess(); + this.javaPersistentType = this.buildJavaPersistentType(); + this.superPersistentType = this.buildSuperPersistentType(); + this.declaringTypeName = this.buildDeclaringTypeName(); + this.initializeAttributes(); + this.metamodelSynchronizer = this.buildMetamodelSynchronizer(); + } + + protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() { + return this.isJpa2_0Compatible() ? + ((JpaFactory2_0) this.getJpaFactory()).buildMetamodelSynchronizer(this) : + null; + } + + + // ********** update ********** + + public void update() { + this.setSpecifiedAccess(this.buildSpecifiedAccess()); + this.setDefaultAccess(this.buildDefaultAccess()); + this.mapping.update(); + this.updateJavaPersistentType(); + this.updateSuperPersistentType(); + this.setDeclaringTypeName(this.buildDeclaringTypeName()); + this.updateAttributes(); + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.javaPersistentType != null) { + this.javaPersistentType.postUpdate(); + } + this.mapping.postUpdate(); + for (PersistentAttribute attribute : this.getAttributes()) { + attribute.postUpdate(); + } + } + + + // ********** name ********** + + public String getName() { + String name = this.mapping.getClass_(); + // nested class names are specified with a '$' in orm.xml + return (name == null) ? null : name.replace('$', '.'); + } + + public String getShortName(){ + String className = this.getName(); + return StringTools.stringIsEmpty(className) ? null : ClassName.getSimpleName(className); + } + + + // ********** mapping ********** + + public OrmTypeMapping getMapping() { + return this.mapping; + } + + public void setMappingKey(String newMappingKey) { + if (this.valuesAreEqual(this.getMappingKey(), newMappingKey)) { + return; + } + OrmTypeMapping oldMapping = this.mapping; + OrmTypeMappingDefinition mappingDefinition = this.getMappingFileDefinition().getOrmTypeMappingDefinition(newMappingKey); + XmlTypeMapping resourceTypeMapping = mappingDefinition.buildResourceMapping(this.getResourceNodeFactory()); + this.mapping = this.buildMapping(resourceTypeMapping); + this.getEntityMappings().changeMapping(this, oldMapping, this.mapping); + this.firePropertyChanged(MAPPING_PROPERTY, oldMapping, this.mapping); + } + + protected OrmTypeMapping buildMapping(XmlTypeMapping resourceMapping) { + OrmTypeMappingDefinition mappingDefintion = this.getMappingFileDefinition().getOrmTypeMappingDefinition(resourceMapping.getMappingKey()); + return mappingDefintion.buildContextMapping(this, resourceMapping, this.getXmlContextNodeFactory()); + } + + + // ********** access ********** + + public AccessType getAccess() { + return (this.specifiedAccess != null) ? this.specifiedAccess : this.defaultAccess; + } + + public AccessType getDefaultAccess() { + return this.defaultAccess; + } + + protected void setDefaultAccess(AccessType defaultAccess) { + AccessType old = this.defaultAccess; + this.defaultAccess = defaultAccess; + this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, defaultAccess); + } + + public AccessType getSpecifiedAccess() { + return this.specifiedAccess; + } + + public void setSpecifiedAccess(AccessType specifiedAccess) { + AccessType old = this.specifiedAccess; + this.specifiedAccess = specifiedAccess; + this.getResourceTypeMapping().setAccess(AccessType.toOrmResourceModel(specifiedAccess)); + this.firePropertyChanged(SPECIFIED_ACCESS_PROPERTY, old, specifiedAccess); + } + + protected AccessType buildDefaultAccess() { + if ( ! this.mapping.isMetadataComplete()) { + if (this.javaPersistentType != null) { + if (this.javaPersistentTypeHasSpecifiedAccess()) { + return this.javaPersistentType.getAccess(); + } + if (this.superPersistentType != null) { + return this.superPersistentType.getAccess(); + } + } + } + AccessType access = this.getMappingFileRoot().getAccess(); + return (access != null) ? access : AccessType.FIELD; //default to FIELD if no specified access found + } + + protected boolean javaPersistentTypeHasSpecifiedAccess() { + return (this.javaPersistentType.getSpecifiedAccess() != null) || + this.javaPersistentType.hasAnyAnnotatedAttributes(); + } + + public AccessType getOwnerOverrideAccess() { + return this.getEntityMappings().getOverridePersistentTypeAccess(); + } + + public AccessType getOwnerDefaultAccess() { + return this.getEntityMappings().getDefaultPersistentTypeAccess(); + } + + protected AccessType buildSpecifiedAccess() { + return AccessType.fromOrmResourceModel(this.getResourceTypeMapping().getAccess()); + } + + + // ********** attributes ********** + + @SuppressWarnings("unchecked") + public ListIterator<OrmPersistentAttribute> attributes() { + return new CompositeListIterator<OrmPersistentAttribute>(this.specifiedAttributes(), this.virtualAttributes()); + } + + @SuppressWarnings("unchecked") + protected Iterable<OrmPersistentAttribute> getAttributes() { + return new CompositeIterable<OrmPersistentAttribute>(this.getSpecifiedAttributes(), this.getVirtualAttributes()); + } + + public int attributesSize() { + return this.specifiedAttributesSize() + this.virtualAttributesSize(); + } + + public Iterator<String> allAttributeNames() { + return this.attributeNames(this.allAttributes()); + } + + public Iterator<PersistentAttribute> allAttributes() { + return new CompositeIterator<PersistentAttribute>( + new TransformationIterator<PersistentType, Iterator<PersistentAttribute>>(this.inheritanceHierarchy()) { + @Override + protected Iterator<PersistentAttribute> transform(PersistentType pt) { + return pt.attributes(); + } + } + ); + } + + protected Iterator<OrmPersistentAttribute> attributesNamed(final String attributeName) { + return new FilteringIterator<OrmPersistentAttribute>(this.attributes()) { + @Override + protected boolean accept(OrmPersistentAttribute o) { + return Tools.valuesAreEqual(attributeName, o.getName()); + } + }; + } + + public OrmPersistentAttribute getAttributeNamed(String attributeName) { + Iterator<OrmPersistentAttribute> stream = this.attributesNamed(attributeName); + return (stream.hasNext()) ? stream.next() : null; + } + + public PersistentAttribute resolveAttribute(String attributeName) { + Iterator<OrmPersistentAttribute> attributes = this.attributesNamed(attributeName); + if (attributes.hasNext()) { + OrmPersistentAttribute attribute = attributes.next(); + return attributes.hasNext() ? null /* more than one */: attribute; + } + return (this.superPersistentType == null) ? null : this.superPersistentType.resolveAttribute(attributeName); + } + + public Iterator<String> attributeNames() { + return this.attributeNames(this.attributes()); + } + + protected Iterator<String> attributeNames(Iterator<? extends PersistentAttribute> attrs) { + return new TransformationIterator<PersistentAttribute, String>(attrs) { + @Override + protected String transform(PersistentAttribute attribute) { + return attribute.getName(); + } + }; + } + + protected void initializeAttributes() { + this.initializeSpecifiedAttributes(); + this.initializeVirtualAttributes(); + } + + protected void updateAttributes() { + this.updateSpecifiedAttributes(); + this.updateVirtualAttributes(); + } + + protected Iterator<JavaResourcePersistentAttribute> javaPersistentAttributes() { + return (this.javaPersistentType == null) ? + EmptyListIterator.<JavaResourcePersistentAttribute>instance() : + this.javaPersistentAttributes(this.javaPersistentType.getResourcePersistentType()); + } + + protected Iterator<JavaResourcePersistentAttribute> javaPersistentAttributes(JavaResourcePersistentType resourcePersistentType) { + AccessType access = this.specifiedAccess; + if (access == null && ! this.mapping.isMetadataComplete()) { + access = this.getJavaPersistentType().getSpecifiedAccess(); + } + if (access == null) { + access = this.defaultAccess; + } + return resourcePersistentType.persistableAttributes(AccessType.toJavaResourceModel(access)); + } + + + // ********** specified attributes ********** + + public ListIterator<OrmPersistentAttribute> specifiedAttributes() { + return new CloneListIterator<OrmPersistentAttribute>(this.specifiedAttributes); + } + + protected Iterable<OrmPersistentAttribute> getSpecifiedAttributes() { + return new LiveCloneIterable<OrmPersistentAttribute>(this.specifiedAttributes); + } + + public int specifiedAttributesSize() { + return this.specifiedAttributes.size(); + } + + protected OrmPersistentAttribute getSpecifiedAttributeFor(final JavaResourcePersistentAttribute jrpa) { + for (OrmPersistentAttribute attribute : this.getSpecifiedAttributes()) { + JavaPersistentAttribute javaAttribute = attribute.getJavaPersistentAttribute(); + if ((javaAttribute != null) && (javaAttribute.getResourcePersistentAttribute() == jrpa)) { + return attribute; + } + } + return null; + } + + public OrmPersistentAttribute addSpecifiedAttribute(String mappingKey, String attributeName) { + Attributes resourceAttributes = this.getResourceAttributes(); + if (resourceAttributes == null) { + resourceAttributes = this.createResourceAttributes(); + this.mapping.getResourceTypeMapping().setAttributes(resourceAttributes); + } + + OrmAttributeMappingDefinition mappingDefintion = this.getMappingFileDefinition().getOrmAttributeMappingDefinition(mappingKey); + XmlAttributeMapping resourceMapping = mappingDefintion.buildResourceMapping(getResourceNodeFactory()); + OrmPersistentAttribute persistentAttribute = this.buildSpecifiedAttribute(resourceMapping); + int index = this.getSpecifiedAttributeInsertionIndex(persistentAttribute); + this.specifiedAttributes.add(index, persistentAttribute); + persistentAttribute.getMapping().addToResourceModel(resourceAttributes); + + persistentAttribute.getSpecifiedMapping().setName(attributeName); + this.fireItemAdded(ATTRIBUTES_LIST, index, persistentAttribute); + return persistentAttribute; + } + + public void changeMapping(OrmPersistentAttribute ormPersistentAttribute, OrmAttributeMapping oldMapping, OrmAttributeMapping newMapping) { + int sourceIndex = this.specifiedAttributes.indexOf(ormPersistentAttribute); + this.specifiedAttributes.remove(sourceIndex); + oldMapping.removeFromResourceModel(this.getResourceAttributes()); + int targetIndex = getSpecifiedAttributeInsertionIndex(ormPersistentAttribute); + this.specifiedAttributes.add(targetIndex, ormPersistentAttribute); + newMapping.addToResourceModel(this.getResourceAttributes()); + oldMapping.initializeOn(newMapping); + this.fireItemMoved(ATTRIBUTES_LIST, targetIndex, sourceIndex); + } + + public void makeAttributeSpecified(OrmPersistentAttribute ormPersistentAttribute) { + this.makeAttributeSpecified(ormPersistentAttribute, ormPersistentAttribute.getMappingKey()); + } + + public void makeAttributeSpecified(OrmPersistentAttribute ormPersistentAttribute, String mappingKey) { + if ( ! ormPersistentAttribute.isVirtual()) { + throw new IllegalStateException("Attribute is already specified"); //$NON-NLS-1$ + } + if (this.valuesAreEqual(mappingKey, MappingKeys.NULL_ATTRIBUTE_MAPPING_KEY)) { + throw new IllegalStateException("Use makePersistentAttributeSpecified(OrmPersistentAttribute, String) instead and specify a mapping type"); //$NON-NLS-1$ + } + + Attributes resourceAttributes = this.getResourceAttributes(); + if (resourceAttributes == null) { + resourceAttributes = this.createResourceAttributes(); + this.mapping.getResourceTypeMapping().setAttributes(resourceAttributes); + } + + OrmAttributeMappingDefinition mappingDefintion = this.getMappingFileDefinition().getOrmAttributeMappingDefinition(mappingKey); + XmlAttributeMapping resourceMapping = mappingDefintion.buildResourceMapping(getResourceNodeFactory()); + + OrmPersistentAttribute newAttribute = this.buildSpecifiedAttribute(resourceMapping); + int insertionIndex = this.getSpecifiedAttributeInsertionIndex(newAttribute); + this.specifiedAttributes.add(insertionIndex, newAttribute); + newAttribute.getMapping().addToResourceModel(resourceAttributes); + + int removalIndex = this.virtualAttributes.indexOf(ormPersistentAttribute); + this.virtualAttributes.remove(ormPersistentAttribute); + newAttribute.getSpecifiedMapping().setName(ormPersistentAttribute.getName()); + if (ormPersistentAttribute.getJavaPersistentAttribute().getSpecifiedAccess() != null) { + newAttribute.setSpecifiedAccess(ormPersistentAttribute.getJavaPersistentAttribute().getSpecifiedAccess()); + } + + this.fireItemAdded(ATTRIBUTES_LIST, insertionIndex, newAttribute); + this.fireItemRemoved(VIRTUAL_ATTRIBUTES_LIST, removalIndex, ormPersistentAttribute); + } + + protected int getSpecifiedAttributeInsertionIndex(OrmPersistentAttribute specifiedAttribute) { + return CollectionTools.insertionIndexOf(this.specifiedAttributes, specifiedAttribute, this.getAttributeComparator()); + } + + protected Comparator<OrmPersistentAttribute> getAttributeComparator() { + return ATTRIBUTE_COMPARATOR; + } + + protected static final Comparator<OrmPersistentAttribute> ATTRIBUTE_COMPARATOR = + new Comparator<OrmPersistentAttribute>() { + public int compare(OrmPersistentAttribute o1, OrmPersistentAttribute o2) { + int o1Sequence = o1.getMapping().getXmlSequence(); + int o2Sequence = o2.getMapping().getXmlSequence(); + return (o1Sequence == o2Sequence) ? 0 : (o1Sequence < o2Sequence) ? -1 : 1; + } + }; + + protected Attributes getResourceAttributes() { + return this.getResourceTypeMapping().getAttributes(); + } + + protected Attributes createResourceAttributes() { + return EmfTools.create(this.getResourceNodeFactory(), OrmPackage.eINSTANCE.getAttributes(), Attributes.class); + } + + protected void initializeSpecifiedAttributes() { + Attributes attributes = this.getResourceAttributes(); + if (attributes == null) { + return; + } + for (XmlAttributeMapping resourceMapping : attributes.getAttributeMappings()) { + this.addSpecifiedAttribute(resourceMapping); + } + } + + protected void updateSpecifiedAttributes() { + Attributes attributes = this.getResourceAttributes(); + Collection<OrmPersistentAttribute> contextAttributesToRemove = CollectionTools.collection(this.specifiedAttributes()); + Collection<OrmPersistentAttribute> contextAttributesToUpdate = new ArrayList<OrmPersistentAttribute>(); + int resourceIndex = 0; + + if (attributes != null) { + for (XmlAttributeMapping resourceMapping : attributes.getAttributeMappings()) { + boolean contextAttributeFound = false; + for (OrmPersistentAttribute contextAttribute : contextAttributesToRemove) { + if (contextAttribute.getMapping().getResourceAttributeMapping() == resourceMapping) { + this.moveSpecifiedAttribute_(resourceIndex, contextAttribute); + contextAttributesToRemove.remove(contextAttribute); + contextAttributesToUpdate.add(contextAttribute); + contextAttributeFound = true; + break; + } + } + if ( ! contextAttributeFound) { + OrmPersistentAttribute ormPersistentAttribute = this.addSpecifiedAttribute(resourceMapping); + this.fireItemAdded(ATTRIBUTES_LIST, specifiedAttributesSize(), ormPersistentAttribute); + } + resourceIndex++; + } + } + for (OrmPersistentAttribute contextAttribute : contextAttributesToRemove) { + this.removeSpecifiedAttribute_(contextAttribute); + } + //first handle adding/removing of the persistent attributes, then update the others last, + //this causes less churn in the update process + for (OrmPersistentAttribute contextAttribute : contextAttributesToUpdate) { + contextAttribute.update(); + } + } + + protected void removeSpecifiedAttribute_(OrmPersistentAttribute ormPersistentAttribute) { + this.removeItemFromList(ormPersistentAttribute, this.specifiedAttributes, ATTRIBUTES_LIST); + } + + //not firing change notification so this can be reused in initialize and update + protected OrmPersistentAttribute addSpecifiedAttribute(XmlAttributeMapping resourceMapping) { + OrmPersistentAttribute ormPersistentAttribute = this.buildSpecifiedAttribute(resourceMapping); + this.specifiedAttributes.add(ormPersistentAttribute); + return ormPersistentAttribute; + } + + protected void moveSpecifiedAttribute_(int index, OrmPersistentAttribute attribute) { + this.moveItemInList(index, this.specifiedAttributes.indexOf(attribute), this.specifiedAttributes, ATTRIBUTES_LIST); + } + + public void removeSpecifiedAttribute(OrmPersistentAttribute ormPersistentAttribute) { + int index = this.specifiedAttributes.indexOf(ormPersistentAttribute); + this.specifiedAttributes.remove(ormPersistentAttribute); + ormPersistentAttribute.getMapping().removeFromResourceModel(this.getResourceAttributes()); + if (this.getResourceAttributes().isUnset()) { + this.mapping.getResourceTypeMapping().setAttributes(null); + } + this.fireItemRemoved(ATTRIBUTES_LIST, index, ormPersistentAttribute); + } + + protected OrmPersistentAttribute buildSpecifiedAttribute(XmlAttributeMapping resourceMapping) { + return this.buildOrmPersistentAttribute(this.buildSpecifiedAttributeOwner(), resourceMapping); + } + + protected OrmPersistentAttribute.Owner buildSpecifiedAttributeOwner() { + return new SpecifiedAttributeOwner(); + } + + protected JavaPersistentAttribute buildJavaPersistentAttribute(JavaResourcePersistentAttribute jrpa) { + return this.getJpaFactory().buildJavaPersistentAttribute(this, jrpa); + } + + + // ********** virtual attributes ********** + + public ListIterator<OrmPersistentAttribute> virtualAttributes() { + return new CloneListIterator<OrmPersistentAttribute>(this.virtualAttributes); + } + + protected Iterable<OrmPersistentAttribute> getVirtualAttributes() { + return new LiveCloneIterable<OrmPersistentAttribute>(this.virtualAttributes); + } + + public int virtualAttributesSize() { + return this.virtualAttributes.size(); + } + + protected void addVirtualAttribute(OrmPersistentAttribute virtualAttribute) { + this.addItemToList(virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST); + } + + protected void removeVirtualAttribute(OrmPersistentAttribute virtualAttribute) { + this.removeItemFromList(virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST); + } + + public boolean containsVirtualAttribute(OrmPersistentAttribute ormPersistentAttribute) { + return this.virtualAttributes.contains(ormPersistentAttribute); + } + + public void makeAttributeVirtual(OrmPersistentAttribute ormPersistentAttribute) { + if (ormPersistentAttribute.isVirtual()) { + throw new IllegalStateException("Attribute is already virtual"); //$NON-NLS-1$ + } + JavaPersistentAttribute javaPersistentAttribute = ormPersistentAttribute.getJavaPersistentAttribute(); + OrmPersistentAttribute virtualAttribute = null; + if (javaPersistentAttribute != null) { + virtualAttribute = this.addVirtualAttribute(javaPersistentAttribute.getResourcePersistentAttribute()); + } + this.removeSpecifiedAttribute(ormPersistentAttribute); + if (virtualAttribute != null) { + this.fireItemAdded(VIRTUAL_ATTRIBUTES_LIST, virtualAttributesSize() - 1, virtualAttribute); + } + } + + protected void initializeVirtualAttributes() { + for (Iterator<JavaResourcePersistentAttribute> stream = this.javaPersistentAttributes(); stream.hasNext(); ) { + JavaResourcePersistentAttribute javaResourceAttribute = stream.next(); + if (this.getSpecifiedAttributeFor(javaResourceAttribute) == null) { + this.addVirtualAttribute(javaResourceAttribute); + } + } + } + + protected void updateVirtualAttributes() { + Collection<OrmPersistentAttribute> contextAttributesToRemove = CollectionTools.collection(this.virtualAttributes()); + Collection<OrmPersistentAttribute> contextAttributesToUpdate = new ArrayList<OrmPersistentAttribute>(); + int resourceIndex = 0; + + for (Iterator<JavaResourcePersistentAttribute> stream = this.javaPersistentAttributes(); stream.hasNext(); ) { + JavaResourcePersistentAttribute javaResourceAttribute = stream.next(); + OrmPersistentAttribute specifiedAttribute = this.getSpecifiedAttributeFor(javaResourceAttribute); + if (specifiedAttribute == null) { + JavaPersistentAttribute javaAttribute = this.getJpaFactory().buildJavaPersistentAttribute(this, javaResourceAttribute); + JavaAttributeMapping javaAttributeMapping = javaAttribute.getMapping(); + if (this.mapping.isMetadataComplete()) { + javaAttributeMapping = javaAttribute.getDefaultMapping(); + } + boolean contextAttributeFound = false; + for (OrmPersistentAttribute contextAttribute : contextAttributesToRemove) { + JavaPersistentAttribute javaPersistentAttribute = contextAttribute.getJavaPersistentAttribute(); + if (javaPersistentAttribute.getResourcePersistentAttribute() == javaResourceAttribute) { + if (this.valuesAreEqual(contextAttribute.getMappingKey(), javaAttributeMapping.getKey())) { + //the mapping key would change if metaDataComplete flag changes, rebuild the orm attribute + contextAttributesToRemove.remove(contextAttribute); + contextAttributesToUpdate.add(contextAttribute); + contextAttributeFound = true; + break; + } + } + } + if ( ! contextAttributeFound) { + OrmPersistentAttribute virtualAttribute = this.addVirtualAttribute(javaAttributeMapping); + this.fireItemAdded(VIRTUAL_ATTRIBUTES_LIST, virtualAttributesSize() - 1, virtualAttribute); + } + resourceIndex++; + } + } + + for (OrmPersistentAttribute contextAttribute : contextAttributesToRemove) { + this.removeVirtualAttribute(contextAttribute); + } + //first handle adding/removing of the persistent attributes, then update the others last, + //this causes less churn in the update process + for (OrmPersistentAttribute contextAttribute : contextAttributesToUpdate) { + contextAttribute.update(); + } + } + + protected OrmPersistentAttribute addVirtualAttribute(JavaResourcePersistentAttribute resourceAttribute) { + JavaPersistentAttribute javaAttribute = this.getJpaFactory().buildJavaPersistentAttribute(this, resourceAttribute); + JavaAttributeMapping javaAttributeMapping = javaAttribute.getMapping(); + if (this.mapping.isMetadataComplete()) { + javaAttributeMapping = javaAttribute.getDefaultMapping(); + } + return this.addVirtualAttribute(javaAttributeMapping); + } + + //not firing change notification so this can be reused in initialize and update + protected OrmPersistentAttribute addVirtualAttribute(JavaAttributeMapping javaAttributeMapping) { + OrmAttributeMappingDefinition mappingDefintion = this.getMappingFileDefinition().getOrmAttributeMappingDefinition(javaAttributeMapping.getKey()); + XmlAttributeMapping resourceMapping = mappingDefintion.buildVirtualResourceMapping(this.mapping, javaAttributeMapping, this.getXmlContextNodeFactory()); + OrmPersistentAttribute virtualAttribute = this.buildVirtualOrmPersistentAttribute(javaAttributeMapping, resourceMapping); + this.virtualAttributes.add(virtualAttribute); + return virtualAttribute; + } + + protected OrmPersistentAttribute buildVirtualOrmPersistentAttribute(JavaAttributeMapping javaAttributeMapping, XmlAttributeMapping resourceMapping) { + return this.buildOrmPersistentAttribute(this.buildVirtualAttributeOwner(javaAttributeMapping.getPersistentAttribute()), resourceMapping); + } + + protected OrmPersistentAttribute buildOrmPersistentAttribute(OrmPersistentAttribute.Owner owner, XmlAttributeMapping resourceMapping) { + return this.getXmlContextNodeFactory().buildOrmPersistentAttribute(this, owner, resourceMapping); + } + + protected OrmPersistentAttribute.Owner buildVirtualAttributeOwner(final JavaPersistentAttribute javaPersistentAttribute) { + return new OrmPersistentAttribute.Owner() { + public JavaPersistentAttribute findJavaPersistentAttribute(OrmPersistentAttribute ormPersistentAttribute) { + return javaPersistentAttribute; + } + + public void updateJavaPersistentAttribute() { + //update the attribute, since we own it and it will not get updated otherwise + javaPersistentAttribute.update(); + } + }; + } + + + // ********** Java persistent type ********** + + public JavaPersistentType getJavaPersistentType() { + return this.javaPersistentType; + } + + protected void setJavaPersistentType(JavaPersistentType javaPersistentType) { + JavaPersistentType old = this.javaPersistentType; + this.javaPersistentType = javaPersistentType; + this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType); + } + + protected JavaPersistentType buildJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + return (jrpt == null) ? null : this.buildJavaPersistentType(jrpt); + } + + protected JavaResourcePersistentType getJavaResourcePersistentType() { + return this.getEntityMappings().resolveJavaResourcePersistentType(this.getName()); + } + + protected JavaResourcePersistentType getJavaResourcePersistentType(String className) { + return this.getJpaProject().getJavaResourcePersistentType(className); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + protected void updateJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + if (jrpt == null) { + this.setJavaPersistentType(null); + } else { + if (this.javaPersistentType == null) { + this.setJavaPersistentType(this.buildJavaPersistentType(jrpt)); + } else { + this.javaPersistentType.update(jrpt); + } + } + } + + + // ********** super persistent type ********** + + public PersistentType getSuperPersistentType() { + return this.superPersistentType; + } + + protected void setSuperPersistentType(PersistentType superPersistentType) { + PersistentType old = this.superPersistentType; + this.superPersistentType = superPersistentType; + this.firePropertyChanged(SUPER_PERSISTENT_TYPE_PROPERTY, old, superPersistentType); + } + + protected void updateSuperPersistentType() { + PersistentType spt = this.buildSuperPersistentType(); + // check for circular inheritance + if ((spt == null) || CollectionTools.contains(spt.inheritanceHierarchy(), this)) { + this.setSuperPersistentType(null); + } else { + this.setSuperPersistentType(spt); + } + } + + protected PersistentType buildSuperPersistentType() { + return (this.javaPersistentType == null) ? null : this.javaPersistentType.getSuperPersistentType(); + } + + + // ********** inheritance ********** + + public Iterator<PersistentType> inheritanceHierarchy() { + return this.inheritanceHierarchyOf(this); + } + + public Iterator<PersistentType> ancestors() { + return this.inheritanceHierarchyOf(this.superPersistentType); + } + + protected Iterator<PersistentType> inheritanceHierarchyOf(PersistentType start) { + // using a chain iterator to traverse up the inheritance tree + return new ChainIterator<PersistentType>(start) { + @Override + protected PersistentType nextLink(PersistentType persistentType) { + return persistentType.getSuperPersistentType(); + } + }; + } + + + // ********** declaring type name ********** + + public String getDeclaringTypeName() { + return this.declaringTypeName; + } + + protected void setDeclaringTypeName(String declaringTypeName) { + String old = this.declaringTypeName; + this.declaringTypeName = declaringTypeName; + this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, declaringTypeName); + } + + protected String buildDeclaringTypeName() { + return this.isJpa2_0Compatible() ? buildDeclaringTypeName_() : null; + } + + protected String buildDeclaringTypeName_() { + return (this.javaPersistentType == null) ? + null : ((JavaPersistentType2_0) this.javaPersistentType).getDeclaringTypeName(); + } + + + // ********** metamodel ********** + + public IFile getMetamodelFile() { + return (this.javaPersistentType == null) ? null : this.metamodelSynchronizer.getFile(); + } + + public void initializeMetamodel() { + // do nothing - probably shouldn't be called... + } + + public boolean isManaged() { + return true; + } + + /** + * All orm.xml persistent types must be able to generate a static metamodel + * because 1.0 orm.xml files can be referenced from 2.0 persistence.xml files. + */ + public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) { + if (this.javaPersistentType != null) { + this.metamodelSynchronizer.synchronize(memberTypeTree); + } + } + + public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) { + if (this.javaPersistentType != null) { + this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree); + } + } + + public void disposeMetamodel() { + // do nothing - probably shouldn't be called... + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return OrmStructureNodes.PERSISTENT_TYPE_ID; + } + + public JpaStructureNode getStructureNode(int textOffset) { + for (OrmPersistentAttribute attribute : this.getSpecifiedAttributes()) { + if (attribute.contains(textOffset)) { + return attribute; + } + } + return this; + } + + public TextRange getSelectionTextRange() { + return this.mapping.getSelectionTextRange(); + } + + public void dispose() { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + } + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getOverridePersistentTypeAccess() { + if (this.specifiedAccess != null) { + return this.specifiedAccess; + } + + if (this.superPersistentType instanceof OrmPersistentType) { + AccessType accessType = ((OrmPersistentType) this.superPersistentType).getSpecifiedAccess(); + if (accessType != null) { + return accessType; + } + } + + if (this.mapping.isMetadataComplete()) { + AccessType accessType = this.getOwnerDefaultAccess(); + if (accessType != null) { + return accessType; + } + } + + // no override access type + return null; + } + + public AccessType getDefaultPersistentTypeAccess() { + if (this.superPersistentType instanceof OrmPersistentType) { + AccessType accessType = ((OrmPersistentType) this.superPersistentType).getDefaultAccess(); + if (accessType != null) { + return accessType; + } + } + + return this.getOwnerDefaultAccess(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateClass(messages); + this.validateMapping(messages, reporter); + this.validateAttributes(messages, reporter); + } + + protected void validateClass(List<IMessage> messages) { + if (this.javaPersistentType == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS, + new String[] {this.getName()}, + this, + this.mapping.getClassTextRange() + ) + ); + } + } + + protected void validateMapping(List<IMessage> messages, IReporter reporter) { + try { + this.mapping.validate(messages, reporter); + } catch(Throwable t) { + JptCorePlugin.log(t); + } + } + + protected void validateAttributes(List<IMessage> messages, IReporter reporter) { + for (Iterator<OrmPersistentAttribute> stream = this.attributes(); stream.hasNext(); ) { + this.validateAttribute(stream.next(), messages, reporter); + } + } + + protected void validateAttribute(OrmPersistentAttribute attribute, List<IMessage> messages, IReporter reporter) { + try { + attribute.validate(messages, reporter); + } catch(Throwable t) { + JptCorePlugin.log(t); + } + } + + public TextRange getValidationTextRange() { + return this.mapping.getValidationTextRange(); + } + + + // ********** misc ********** + + @Override + public EntityMappings getParent() { + return (EntityMappings) super.getParent(); + } + + public String getDefaultPackage() { + return this.getEntityMappings().getPackage(); + } + + public boolean isDefaultMetadataComplete() { + return this.getEntityMappings().isDefaultPersistentTypeMetadataComplete(); + } + + public boolean isFor(String typeName) { + String className = this.getName(); + if (className == null) { + return false; + } + if (className.equals(typeName)) { + return true; + } + String defaultPackage = this.getDefaultPackage(); + if (defaultPackage == null) { + return false; + } + return (defaultPackage + '.' + className).equals(typeName); + } + + public boolean contains(int textOffset) { + return this.mapping.containsOffset(textOffset); + } + + public void classChanged(String oldClass, String newClass) { + this.firePropertyChanged(NAME_PROPERTY, oldClass, newClass); + } + + public boolean isMapped() { + return true; + } + + public String getMappingKey() { + return this.mapping.getKey(); + } + + protected EntityMappings getEntityMappings() { + return this.getParent(); + } + + protected XmlTypeMapping getResourceTypeMapping() { + return this.mapping.getResourceTypeMapping(); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.getName()); + } + + + // ********** specified persistent attribute owner ********** + + protected class SpecifiedAttributeOwner + implements OrmPersistentAttribute.Owner + { + private JavaPersistentAttribute cachedJavaPersistentAttribute; + + public SpecifiedAttributeOwner() { + super(); + } + + public JavaPersistentAttribute findJavaPersistentAttribute(OrmPersistentAttribute ormPersistentAttribute) { + if (GenericOrmPersistentType.this.javaPersistentType == null) { + return null; + } + String ormName = ormPersistentAttribute.getName(); + if (ormName == null) { + return null; + } + AccessType ormAccess = ormPersistentAttribute.getAccess(); + + JavaPersistentAttribute javaPersistentAttribute = this.findExistingJavaPersistentAttribute(ormName); + if ((javaPersistentAttribute != null) && (javaPersistentAttribute.getAccess() == ormAccess)) { + this.cachedJavaPersistentAttribute = null; // we only want to cache the persistent attribute if we build it + return javaPersistentAttribute; + } + + // if 'javaPersistentAttribute' is null, it might exist in a superclass that is not persistent, we need to build it ourselves. + // if access is different, we won't be able to find the corresponding java persistent attribute, it won't exist so we build it ourselves + return this.buildJavaPersistentAttribute(ormName, ormAccess); + } + + protected JavaPersistentAttribute findExistingJavaPersistentAttribute(String attributeName) { + return GenericOrmPersistentType.this.javaPersistentType.getAttributeNamed(attributeName); + } + + protected JavaPersistentAttribute buildJavaPersistentAttribute(String ormName, AccessType ormAccess) { + JavaResourcePersistentAttribute jrpa = this.getJavaResourcePersistentAttribute(this.getJavaResourcePersistentType(), ormName, ormAccess); + if (this.cachedJavaPersistentAttribute != null && + this.cachedJavaPersistentAttribute.getResourcePersistentAttribute() == jrpa) { + return this.cachedJavaPersistentAttribute; + } + return this.cachedJavaPersistentAttribute = (jrpa == null) ? null : GenericOrmPersistentType.this.buildJavaPersistentAttribute(jrpa); + } + + protected JavaResourcePersistentType getJavaResourcePersistentType() { + return GenericOrmPersistentType.this.javaPersistentType.getResourcePersistentType(); + } + + protected JavaResourcePersistentAttribute getJavaResourcePersistentAttribute(JavaResourcePersistentType javaResourcePersistentType, String ormName, AccessType ormAccess) { + for (Iterator<JavaResourcePersistentAttribute> stream = this.attributes(javaResourcePersistentType, ormAccess); stream.hasNext(); ) { + JavaResourcePersistentAttribute jrpa = stream.next(); + if (jrpa.getName().equals(ormName)) { + return jrpa; + } + } + // climb up inheritance hierarchy + String superclassName = javaResourcePersistentType.getSuperclassQualifiedName(); + if (superclassName == null) { + return null; + } + JavaResourcePersistentType superclass = GenericOrmPersistentType.this.getJavaResourcePersistentType(superclassName); + if (superclass == null) { + return null; + } + // recurse + return this.getJavaResourcePersistentAttribute(superclass, ormName, ormAccess); + } + + protected Iterator<JavaResourcePersistentAttribute> attributes(JavaResourcePersistentType javaResourcePersistentType, AccessType ormAccess) { + return (ormAccess == AccessType.PROPERTY) ? javaResourcePersistentType.persistableProperties() : javaResourcePersistentType.persistableFields(); + } + + public void updateJavaPersistentAttribute() { + if (this.cachedJavaPersistentAttribute != null) { + this.cachedJavaPersistentAttribute.update(); + } + //else { + //don't update, we don't own the java persistent attribute, + //it will be updated through the java context model + //} + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..4e4f893c5a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.core.context.PrimaryKeyJoinColumn; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmBaseJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmNamedColumn; +import org.eclipse.jpt.core.resource.orm.XmlPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Column; +import org.eclipse.jpt.db.Table; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class GenericOrmPrimaryKeyJoinColumn extends AbstractOrmNamedColumn<XmlPrimaryKeyJoinColumn> + implements OrmPrimaryKeyJoinColumn +{ + protected String specifiedReferencedColumnName; + + protected String defaultReferencedColumnName; + + protected XmlPrimaryKeyJoinColumn resourcePkJoinColumn; + + public GenericOrmPrimaryKeyJoinColumn(XmlContextNode parent, OrmBaseJoinColumn.Owner owner, XmlPrimaryKeyJoinColumn resourcePkJoinColumn) { + super(parent, owner); + this.initialize(resourcePkJoinColumn); + } + + public void initializeFrom(PrimaryKeyJoinColumn oldPkJoinColumn) { + super.initializeFrom(oldPkJoinColumn); + setSpecifiedReferencedColumnName(oldPkJoinColumn.getSpecifiedReferencedColumnName()); + } + + @Override + protected XmlPrimaryKeyJoinColumn getResourceColumn() { + return this.resourcePkJoinColumn; + } + + @Override + protected void addResourceColumn() { + //primaryKeyJoinColumns are part of a collection, the pk-join-column element will be removed/added + //when the XmlPrimaryKeyJoinColumn is removed/added to the XmlEntity collection + } + + @Override + protected void removeResourceColumn() { + //primaryKeyJoinColumns are part of a collection, the pk-join-column element will be removed/added + //when the XmlPrimaryKeyJoinColumn is removed/added to the XmlEntity collection + } + + public String getReferencedColumnName() { + return (this.getSpecifiedReferencedColumnName() == null) ? getDefaultReferencedColumnName() : this.getSpecifiedReferencedColumnName(); + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + getResourceColumn().setReferencedColumnName(newSpecifiedReferencedColumnName); + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + protected void setSpecifiedReferencedColumnName_(String newSpecifiedReferencedColumnName) { + String oldSpecifiedReferencedColumnName = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = newSpecifiedReferencedColumnName; + firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, oldSpecifiedReferencedColumnName, newSpecifiedReferencedColumnName); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String newDefaultReferencedColumnName) { + String oldDefaultReferencedColumnName = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = newDefaultReferencedColumnName; + firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, oldDefaultReferencedColumnName, newDefaultReferencedColumnName); + } + + @Override + public OrmBaseJoinColumn.Owner getOwner() { + return (OrmBaseJoinColumn.Owner) this.owner; + } + + public Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public Table getReferencedColumnDbTable() { + return getOwner().getReferencedColumnDbTable(); + } + + public boolean isReferencedColumnResolved() { + return getReferencedDbColumn() != null; + } + + public TextRange getReferencedColumnNameTextRange() { + if (getResourceColumn() != null) { + TextRange textRange = getResourceColumn().getReferencedColumnNameTextRange(); + if (textRange != null) { + return textRange; + } + } + return getOwner().getValidationTextRange(); + } + + + public boolean isVirtual() { + return getOwner().isVirtual(this); + } + + @Override + public String getTable() { + return getOwner().getDefaultTableName(); + } + + @Override + protected void initialize(XmlPrimaryKeyJoinColumn resourcePkJoinColumn) { + this.resourcePkJoinColumn = resourcePkJoinColumn; + super.initialize(resourcePkJoinColumn); + this.specifiedReferencedColumnName = getResourceReferencedColumnName(); + this.defaultReferencedColumnName = buildDefaultReferencedColumnName(); + } + + @Override + public void update(XmlPrimaryKeyJoinColumn resourcePkJoinColumn) { + this.resourcePkJoinColumn = resourcePkJoinColumn; + super.update(resourcePkJoinColumn); + this.setSpecifiedReferencedColumnName_(getResourceReferencedColumnName()); + this.setDefaultReferencedColumnName(buildDefaultReferencedColumnName()); + } + + protected String getResourceReferencedColumnName() { + return this.resourcePkJoinColumn == null ? null : this.resourcePkJoinColumn.getReferencedColumnName(); + } + + //TODO not correct when we start supporting primaryKeyJoinColumns in 1-1 mappings + protected String buildDefaultReferencedColumnName() { + return buildDefaultName(); + } + + + //******************* validation *********************** + + @Override + //this method will only be called if the table validates correctly + protected void validateName(List<IMessage> messages) { + //do not call super here, first need to check for multiple join columns errors + this.validateJoinColumnName(messages); + this.validateReferencedColumnName(messages); + } + + protected void validateJoinColumnName(List<IMessage> messages) { + if (this.getSpecifiedName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedNameMultipleJoinColumnsMessage()); + } + else if (this.getName() != null){ + super.validateName(messages); + } + //If the name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected void validateReferencedColumnName(List<IMessage> messages) { + if (this.getSpecifiedReferencedColumnName() == null && this.getOwner().joinColumnsSize() > 1) { + messages.add(this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage()); + } + else if (this.getReferencedColumnName() != null) { + Table refColumnDbTable = this.getReferencedColumnDbTable(); + if (refColumnDbTable != null && ! this.isReferencedColumnResolved()) { + messages.add(getOwner().buildUnresolvedReferencedColumnNameMessage(this, this.getReferencedColumnNameTextRange())); + } + } + //If the referenced column name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return getOwner().buildUnspecifiedNameMultipleJoinColumnsMessage(this, getNameTextRange()); + } + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return getOwner().buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(this, getReferencedColumnNameTextRange()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java new file mode 100644 index 0000000000..0fdb1b918a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import org.eclipse.jpt.core.context.NamedNativeQuery; +import org.eclipse.jpt.core.context.NamedQuery; +import org.eclipse.jpt.core.context.Query; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmNamedNativeQuery; +import org.eclipse.jpt.core.context.orm.OrmNamedQuery; +import org.eclipse.jpt.core.context.orm.OrmQuery; +import org.eclipse.jpt.core.context.orm.OrmQueryContainer; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlNamedNativeQuery; +import org.eclipse.jpt.core.resource.orm.XmlNamedQuery; +import org.eclipse.jpt.core.resource.orm.XmlQueryContainer; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.CompositeIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmQueryContainer extends AbstractOrmXmlContextNode + implements OrmQueryContainer +{ + protected final XmlQueryContainer resourceQueryContainer; + + protected final List<OrmNamedQuery> namedQueries; + + protected final List<OrmNamedNativeQuery> namedNativeQueries; + + + public GenericOrmQueryContainer(XmlContextNode parent, XmlQueryContainer resourceQueryContainer) { + super(parent); + this.resourceQueryContainer = resourceQueryContainer; + this.namedQueries = new ArrayList<OrmNamedQuery>(); + this.namedNativeQueries = new ArrayList<OrmNamedNativeQuery>(); + this.initializeNamedQueries(); + this.initializeNamedNativeQueries(); + } + + public ListIterator<OrmNamedQuery> namedQueries() { + return new CloneListIterator<OrmNamedQuery>(this.namedQueries); + } + + public int namedQueriesSize() { + return this.namedQueries.size(); + } + + public OrmNamedQuery addNamedQuery(int index) { + XmlNamedQuery resourceNamedQuery = OrmFactory.eINSTANCE.createXmlNamedQuery(); + OrmNamedQuery contextNamedQuery = buildNamedQuery(resourceNamedQuery); + this.namedQueries.add(index, contextNamedQuery); + this.resourceQueryContainer.getNamedQueries().add(index, resourceNamedQuery); + this.fireItemAdded(NAMED_QUERIES_LIST, index, contextNamedQuery); + return contextNamedQuery; + } + + protected void addNamedQuery(int index, OrmNamedQuery namedQuery) { + addItemToList(index, namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + protected void addNamedQuery(OrmNamedQuery namedQuery) { + this.addNamedQuery(this.namedQueries.size(), namedQuery); + } + + public void removeNamedQuery(NamedQuery namedQuery) { + removeNamedQuery(this.namedQueries.indexOf(namedQuery)); + } + + public void removeNamedQuery(int index) { + OrmNamedQuery namedQuery = this.namedQueries.remove(index); + this.resourceQueryContainer.getNamedQueries().remove(index); + fireItemRemoved(NAMED_QUERIES_LIST, index, namedQuery); + } + + protected void removeNamedQuery_(OrmNamedQuery namedQuery) { + removeItemFromList(namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + public void moveNamedQuery(int targetIndex, int sourceIndex) { + CollectionTools.move(this.namedQueries, targetIndex, sourceIndex); + this.resourceQueryContainer.getNamedQueries().move(targetIndex, sourceIndex); + fireItemMoved(NAMED_QUERIES_LIST, targetIndex, sourceIndex); + } + + public ListIterator<OrmNamedNativeQuery> namedNativeQueries() { + return new CloneListIterator<OrmNamedNativeQuery>(this.namedNativeQueries); + } + + public int namedNativeQueriesSize() { + return this.namedNativeQueries.size(); + } + + public OrmNamedNativeQuery addNamedNativeQuery(int index) { + XmlNamedNativeQuery resourceNamedNativeQuery = OrmFactory.eINSTANCE.createXmlNamedNativeQuery(); + OrmNamedNativeQuery contextNamedNativeQuery = buildNamedNativeQuery(resourceNamedNativeQuery); + this.namedNativeQueries.add(index, contextNamedNativeQuery); + this.resourceQueryContainer.getNamedNativeQueries().add(index, resourceNamedNativeQuery); + this.fireItemAdded(NAMED_NATIVE_QUERIES_LIST, index, contextNamedNativeQuery); + return contextNamedNativeQuery; + } + + protected void addNamedNativeQuery(int index, OrmNamedNativeQuery namedNativeQuery) { + addItemToList(index, namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + protected void addNamedNativeQuery(OrmNamedNativeQuery namedNativeQuery) { + this.addNamedNativeQuery(this.namedNativeQueries.size(), namedNativeQuery); + } + + public void removeNamedNativeQuery(NamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + public void removeNamedNativeQuery(int index) { + OrmNamedNativeQuery namedNativeQuery = this.namedNativeQueries.remove(index); + this.resourceQueryContainer.getNamedNativeQueries().remove(index); + fireItemRemoved(NAMED_NATIVE_QUERIES_LIST, index, namedNativeQuery); + } + + protected void removeNamedNativeQuery_(OrmNamedNativeQuery namedNativeQuery) { + removeItemFromList(namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + public void moveNamedNativeQuery(int targetIndex, int sourceIndex) { + CollectionTools.move(this.namedNativeQueries, targetIndex, sourceIndex); + this.resourceQueryContainer.getNamedNativeQueries().move(targetIndex, sourceIndex); + fireItemMoved(NAMED_NATIVE_QUERIES_LIST, targetIndex, sourceIndex); + } + + + protected void initializeNamedQueries() { + for (XmlNamedQuery namedQuery : this.resourceQueryContainer.getNamedQueries()) { + this.namedQueries.add(buildNamedQuery(namedQuery)); + } + } + + protected void initializeNamedNativeQueries() { + for (XmlNamedNativeQuery namedNativeQuery : this.resourceQueryContainer.getNamedNativeQueries()) { + this.namedNativeQueries.add(buildNamedNativeQuery(namedNativeQuery)); + } + } + + public void update() { + this.updateNamedQueries(); + this.updateNamedNativeQueries(); + } + + protected void updateNamedQueries() { + // make a copy of the XML queries (to prevent ConcurrentModificationException) + Iterator<XmlNamedQuery> xmlQueries = new CloneIterator<XmlNamedQuery>(this.resourceQueryContainer.getNamedQueries()); + + for (Iterator<OrmNamedQuery> contextQueries = this.namedQueries(); contextQueries.hasNext(); ) { + OrmNamedQuery contextQuery = contextQueries.next(); + if (xmlQueries.hasNext()) { + contextQuery.update(xmlQueries.next()); + } + else { + removeNamedQuery_(contextQuery); + } + } + + while (xmlQueries.hasNext()) { + addNamedQuery(buildNamedQuery(xmlQueries.next())); + } + } + + protected OrmNamedQuery buildNamedQuery(XmlNamedQuery resourceNamedQuery) { + return getXmlContextNodeFactory().buildOrmNamedQuery(this, resourceNamedQuery); + } + + protected void updateNamedNativeQueries() { + // make a copy of the XML queries (to prevent ConcurrentModificationException) + Iterator<XmlNamedNativeQuery> xmlQueries = new CloneIterator<XmlNamedNativeQuery>(this.resourceQueryContainer.getNamedNativeQueries()); + + for (Iterator<OrmNamedNativeQuery> contextQueries = this.namedNativeQueries(); contextQueries.hasNext(); ) { + OrmNamedNativeQuery contextQuery = contextQueries.next(); + if (xmlQueries.hasNext()) { + contextQuery.update(xmlQueries.next()); + } + else { + removeNamedNativeQuery_(contextQuery); + } + } + + while (xmlQueries.hasNext()) { + addNamedNativeQuery(buildNamedNativeQuery(xmlQueries.next())); + } + } + + protected OrmNamedNativeQuery buildNamedNativeQuery(XmlNamedNativeQuery resourceNamedNativeQuery) { + return getXmlContextNodeFactory().buildOrmNamedNativeQuery(this, resourceNamedNativeQuery); + } + + + //************ validation *************** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateQueries(messages); + } + + protected void validateQueries(List<IMessage> messages) { + for (Iterator<OrmQuery> localQueries = this.queries(); localQueries.hasNext(); ) { + OrmQuery localQuery = localQueries.next(); + for (Iterator<Query> globalQueries = this.getPersistenceUnit().queries(); globalQueries.hasNext(); ) { + if (localQuery.duplicates(globalQueries.next())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_DUPLICATE_NAME, + new String[] {localQuery.getName()}, + localQuery, + localQuery.getNameTextRange()) + ); + } + } + } + } + + /** + * Return all the queries, named and named native. + */ + @SuppressWarnings("unchecked") + protected Iterator<OrmQuery> queries() { + return new CompositeIterator<OrmQuery>( + namedQueries(), + namedNativeQueries() + ); + } + + public TextRange getValidationTextRange() { + return this.resourceQueryContainer.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryHint.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryHint.java new file mode 100644 index 0000000000..ff733e3dd8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmQueryHint.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.QueryHint; +import org.eclipse.jpt.core.context.orm.OrmQuery; +import org.eclipse.jpt.core.context.orm.OrmQueryHint; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlQueryHint; +import org.eclipse.jpt.core.utility.TextRange; + + +public class GenericOrmQueryHint extends AbstractOrmXmlContextNode implements OrmQueryHint +{ + + protected String name; + + protected String value; + + protected XmlQueryHint resourceQueryHint; + + public GenericOrmQueryHint(OrmQuery parent, XmlQueryHint resourceQueryHint) { + super(parent); + this.initialize(resourceQueryHint); + } + + public String getName() { + return this.name; + } + + public void setName(String newName) { + String oldName = this.name; + this.name = newName; + this.resourceQueryHint.setName(newName); + firePropertyChanged(QueryHint.NAME_PROPERTY, oldName, newName); + } + + public String getValue() { + return this.value; + } + + public void setValue(String newValue) { + String oldValue = this.value; + this.value = newValue; + this.resourceQueryHint.setValue(newValue); + firePropertyChanged(QueryHint.VALUE_PROPERTY, oldValue, newValue); + } + + protected void initialize(XmlQueryHint resourceQueryHint) { + this.resourceQueryHint = resourceQueryHint; + this.name = resourceQueryHint.getName(); + this.value = resourceQueryHint.getValue(); + } + + public void update(XmlQueryHint resourceQueryHint) { + this.resourceQueryHint = resourceQueryHint; + this.setName(resourceQueryHint.getName()); + this.setValue(resourceQueryHint.getValue()); + } + + public TextRange getValidationTextRange() { + return this.resourceQueryHint.getValidationTextRange(); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java new file mode 100644 index 0000000000..03a982521d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.PersistentAttribute; +import org.eclipse.jpt.core.context.ReferenceTable; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmReferenceTable; +import org.eclipse.jpt.core.internal.context.MappingTools; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.AbstractXmlReferenceTable; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlJoinColumn; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class GenericOrmReferenceTable + extends AbstractOrmTable + implements OrmReferenceTable +{ + protected OrmJoinColumn defaultJoinColumn; + + protected final Vector<OrmJoinColumn> specifiedJoinColumns = new Vector<OrmJoinColumn>(); + protected final OrmJoinColumn.Owner joinColumnOwner; + + + protected GenericOrmReferenceTable(XmlContextNode parent) { + super(parent); + this.joinColumnOwner = this.buildJoinColumnOwner(); + } + + protected abstract OrmJoinColumn.Owner buildJoinColumnOwner(); + + public void initializeFrom(ReferenceTable oldReferenceTable) { + super.initializeFrom(oldReferenceTable); + for (Iterator<OrmJoinColumn> stream = oldReferenceTable.specifiedJoinColumns(); stream.hasNext(); ) { + this.addSpecifiedJoinColumnFrom(stream.next()); + } + } + + protected void initialize(AbstractXmlReferenceTable xmlReferenceTable) { + super.initialize(xmlReferenceTable); + this.initializeSpecifiedJoinColumns(xmlReferenceTable); + this.initializeDefaultJoinColumn(); + } + + public void update() { + this.update(this.getResourceTable()); + } + + protected void update(AbstractXmlReferenceTable xmlReferenceTable) { + super.update(xmlReferenceTable); + this.updateSpecifiedJoinColumns(xmlReferenceTable); + this.updateDefaultJoinColumn(); + } + + + // ********** AbstractOrmTable implementation ********** + + /** + * if the join table is on the "mappedBy" side, it's bogus; + * so don't give it a default schema + */ + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + @Override + protected abstract AbstractXmlReferenceTable getResourceTable(); + + + // ********** join columns ********** + + public ListIterator<OrmJoinColumn> joinColumns() { + return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumns() : this.defaultJoinColumns(); + } + + public int joinColumnsSize() { + return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumnsSize() : this.defaultJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedJoinColumn() { + MappingTools.convertReferenceTableDefaultToSpecifiedJoinColumn(this); + } + + + // ********** default join column ********** + + public OrmJoinColumn getDefaultJoinColumn() { + return this.defaultJoinColumn; + } + + protected void setDefaultJoinColumn(OrmJoinColumn defaultJoinColumn) { + OrmJoinColumn old = this.defaultJoinColumn; + this.defaultJoinColumn = defaultJoinColumn; + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, old, defaultJoinColumn); + } + + protected ListIterator<OrmJoinColumn> defaultJoinColumns() { + if (this.defaultJoinColumn != null) { + return new SingleElementListIterator<OrmJoinColumn>(this.defaultJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultJoinColumnsSize() { + return (this.defaultJoinColumn == null) ? 0 : 1; + } + + protected void initializeDefaultJoinColumn() { + if (this.shouldBuildDefaultJoinColumn()) { + this.defaultJoinColumn = this.buildJoinColumn(null); + } + } + + protected void updateDefaultJoinColumn() { + if (this.shouldBuildDefaultJoinColumn()) { + if (this.defaultJoinColumn == null) { + this.setDefaultJoinColumn(this.buildJoinColumn(null)); + } else { + this.defaultJoinColumn.update(null); + } + } else { + this.setDefaultJoinColumn(null); + } + } + + protected boolean shouldBuildDefaultJoinColumn() { + return ! this.hasSpecifiedJoinColumns(); + } + + + // ********** specified join columns ********** + + public ListIterator<OrmJoinColumn> specifiedJoinColumns() { + return new CloneListIterator<OrmJoinColumn>(this.specifiedJoinColumns); + } + + public int specifiedJoinColumnsSize() { + return this.specifiedJoinColumns.size(); + } + + public boolean hasSpecifiedJoinColumns() { + return this.specifiedJoinColumns.size() != 0; + } + + protected void addSpecifiedJoinColumnFrom(OrmJoinColumn oldJoinColumn) { + OrmJoinColumn newJoinColumn = this.addSpecifiedJoinColumn(this.specifiedJoinColumns.size()); + newJoinColumn.initializeFrom(oldJoinColumn); + } + + public OrmJoinColumn addSpecifiedJoinColumn(int index) { + if (this.getResourceTable() == null) { + this.addResourceTable(); + } + XmlJoinColumn xmlJoinColumn = OrmFactory.eINSTANCE.createXmlJoinColumn(); + OrmJoinColumn joinColumn = this.buildJoinColumn(xmlJoinColumn); + this.specifiedJoinColumns.add(index, joinColumn); + this.getResourceTable().getJoinColumns().add(index, xmlJoinColumn); + this.fireItemAdded(SPECIFIED_JOIN_COLUMNS_LIST, index, joinColumn); + return joinColumn; + } + + protected void addSpecifiedJoinColumn(int index, OrmJoinColumn joinColumn) { + this.addItemToList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedJoinColumn(OrmJoinColumn joinColumn) { + this.addSpecifiedJoinColumn(this.specifiedJoinColumns.size(), joinColumn); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedJoinColumn(this.specifiedJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedJoinColumn(int index) { + OrmJoinColumn removedJoinColumn = this.specifiedJoinColumns.remove(index); + if ( ! this.hasSpecifiedJoinColumns()) { + //create the defaultJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultJoinColumn = this.buildJoinColumn(null); + } + this.getResourceTable().getJoinColumns().remove(index); + this.fireItemRemoved(SPECIFIED_JOIN_COLUMNS_LIST, index, removedJoinColumn); + if (this.defaultJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, null, this.defaultJoinColumn); + } + } + + protected void removeSpecifiedJoinColumn_(OrmJoinColumn joinColumn) { + this.removeItemFromList(joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedJoinColumns, targetIndex, sourceIndex); + this.getResourceTable().getJoinColumns().move(targetIndex, sourceIndex); + this.fireItemMoved(SPECIFIED_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + public void clearSpecifiedJoinColumns() { + this.specifiedJoinColumns.clear(); + this.defaultJoinColumn = this.buildJoinColumn(null); + this.getResourceTable().getJoinColumns().clear(); + this.fireListCleared(SPECIFIED_JOIN_COLUMNS_LIST); + this.firePropertyChanged(DEFAULT_JOIN_COLUMN, null, this.defaultJoinColumn); + } + + protected OrmJoinColumn buildJoinColumn(XmlJoinColumn resourceJoinColumn) { + return this.buildJoinColumn(resourceJoinColumn, this.joinColumnOwner); + } + + protected void initializeSpecifiedJoinColumns(AbstractXmlReferenceTable xmlReferenceTable) { + if (xmlReferenceTable != null) { + for (XmlJoinColumn xmlJoinColumn : xmlReferenceTable.getJoinColumns()) { + this.specifiedJoinColumns.add(this.buildJoinColumn(xmlJoinColumn)); + } + } + } + + protected void updateSpecifiedJoinColumns(AbstractXmlReferenceTable xmlReferenceTable) { + Iterator<XmlJoinColumn> xmlJoinColumns = this.xmlJoinColumns(xmlReferenceTable); + + for (Iterator<OrmJoinColumn> contextJoinColumns = this.specifiedJoinColumns(); contextJoinColumns.hasNext(); ) { + OrmJoinColumn contextJoinColumn = contextJoinColumns.next(); + if (xmlJoinColumns.hasNext()) { + contextJoinColumn.update(xmlJoinColumns.next()); + } else { + this.removeSpecifiedJoinColumn_(contextJoinColumn); + } + } + + while (xmlJoinColumns.hasNext()) { + this.addSpecifiedJoinColumn(this.buildJoinColumn(xmlJoinColumns.next())); + } + } + + protected Iterator<XmlJoinColumn> xmlJoinColumns(AbstractXmlReferenceTable xmlReferenceTable) { + // make a copy of the XML join columns (to prevent ConcurrentModificationException) + return (xmlReferenceTable == null) ? EmptyIterator.<XmlJoinColumn>instance() + : new CloneIterator<XmlJoinColumn>(xmlReferenceTable.getJoinColumns()); + } + + + // ********** misc ********** + + protected OrmJoinColumn buildJoinColumn(XmlJoinColumn resourceJoinColumn, OrmJoinColumn.Owner owner) { + return this.getXmlContextNodeFactory().buildOrmJoinColumn(this, owner, resourceJoinColumn); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + boolean continueValidating = true; + if (this.shouldValidateAgainstDatabase()) { + continueValidating = this.validateAgainstDatabase(messages, reporter); + } + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + this.validateJoinColumns(messages, reporter); + } + } + protected abstract boolean shouldValidateAgainstDatabase(); + + protected boolean validateAgainstDatabase(List<IMessage> messages, IReporter reporter) { + PersistentAttribute persistentAttribute = this.getPersistentAttribute(); + if ( ! this.hasResolvedCatalog()) { + if (persistentAttribute.isVirtual()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getVirtualAttributeUnresolvedCatalogMessageId(), + new String[] {persistentAttribute.getName(), this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange() + ) + ); + } else { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getUnresolvedCatalogMessageId(), + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange() + ) + ); + } + return false; + } + + if ( ! this.hasResolvedSchema()) { + if (persistentAttribute.isVirtual()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getVirtualAttributeUnresolvedSchemaMessageId(), + new String[] {persistentAttribute.getName(), this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange() + ) + ); + } else { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getUnresolvedSchemaMessageId(), + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange() + ) + ); + } + return false; + } + if ( ! this.isResolved()) { + if (getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined + if (persistentAttribute.isVirtual()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getVirtualAttributeUnresolvedNameMessageId(), + new String[] {persistentAttribute.getName(), this.getName()}, + this, + this.getNameTextRange() + ) + ); + } + else { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + getUnresolvedNameMessageId(), + new String[] {this.getName()}, + this, + this.getNameTextRange()) + ); + } + } + return false; + } + return true; + } + + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter) { + this.validateJoinColumns(this.joinColumns(), messages, reporter); + } + + protected void validateJoinColumns(Iterator<OrmJoinColumn> joinColumns, List<IMessage> messages, IReporter reporter) { + while (joinColumns.hasNext()) { + joinColumns.next().validate(messages, reporter); + } + } + + protected abstract String getUnresolvedCatalogMessageId(); + + protected abstract String getUnresolvedSchemaMessageId(); + + protected abstract String getUnresolvedNameMessageId(); + + protected abstract String getVirtualAttributeUnresolvedCatalogMessageId(); + + protected abstract String getVirtualAttributeUnresolvedSchemaMessageId(); + + protected abstract String getVirtualAttributeUnresolvedNameMessageId(); + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java new file mode 100644 index 0000000000..ad7faba7f9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java @@ -0,0 +1,509 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jpt.core.context.BaseJoinColumn; +import org.eclipse.jpt.core.context.Entity; +import org.eclipse.jpt.core.context.NamedColumn; +import org.eclipse.jpt.core.context.PrimaryKeyJoinColumn; +import org.eclipse.jpt.core.context.SecondaryTable; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmBaseJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmEntity; +import org.eclipse.jpt.core.context.orm.OrmPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmSecondaryTable; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlPrimaryKeyJoinColumn; +import org.eclipse.jpt.core.resource.orm.XmlSecondaryTable; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * orm.xml secondary table + */ +public class GenericOrmSecondaryTable + extends AbstractOrmTable + implements OrmSecondaryTable +{ + protected XmlSecondaryTable secondaryTable; + + protected final Vector<OrmPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns = new Vector<OrmPrimaryKeyJoinColumn>(); + + protected OrmPrimaryKeyJoinColumn defaultPrimaryKeyJoinColumn; + + protected final OrmBaseJoinColumn.Owner joinColumnOwner; + + + public GenericOrmSecondaryTable(OrmEntity parent, XmlSecondaryTable xmlSecondaryTable) { + super(parent); + this.joinColumnOwner = this.buildJoinColumnOwner(); + this.initialize(xmlSecondaryTable); + } + + protected OrmBaseJoinColumn.Owner buildJoinColumnOwner() { + return new PrimaryKeyJoinColumnOwner(); + } + + public void initializeFrom(SecondaryTable oldSecondaryTable) { + super.initializeFrom(oldSecondaryTable); + for (PrimaryKeyJoinColumn oldPkJoinColumn : CollectionTools.iterable(oldSecondaryTable.specifiedPrimaryKeyJoinColumns())) { + OrmPrimaryKeyJoinColumn newPkJoinColumn = addSpecifiedPrimaryKeyJoinColumn(specifiedPrimaryKeyJoinColumnsSize()); + newPkJoinColumn.initializeFrom(oldPkJoinColumn); + } + } + + @Override + public OrmEntity getParent() { + return (OrmEntity) super.getParent(); + } + + public OrmEntity getOrmEntity() { + return getParent(); + } + + public OrmPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() { + return this.defaultPrimaryKeyJoinColumn; + } + + protected void setDefaultPrimaryKeyJoinColumn(OrmPrimaryKeyJoinColumn newPkJoinColumn) { + OrmPrimaryKeyJoinColumn oldPkJoinColumn = this.defaultPrimaryKeyJoinColumn; + this.defaultPrimaryKeyJoinColumn = newPkJoinColumn; + firePropertyChanged(SecondaryTable.DEFAULT_PRIMARY_KEY_JOIN_COLUMN, oldPkJoinColumn, newPkJoinColumn); + } + + public ListIterator<OrmPrimaryKeyJoinColumn> primaryKeyJoinColumns() { + return this.containsSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumns() : this.defaultPrimaryKeyJoinColumns(); + } + + public int primaryKeyJoinColumnsSize() { + return this.containsSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumnsSize() : this.defaultPrimaryKeyJoinColumnsSize(); + } + + public ListIterator<OrmPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns() { + return new CloneListIterator<OrmPrimaryKeyJoinColumn>(this.specifiedPrimaryKeyJoinColumns); + } + + public int specifiedPrimaryKeyJoinColumnsSize() { + return this.specifiedPrimaryKeyJoinColumns.size(); + } + + protected ListIterator<OrmPrimaryKeyJoinColumn> defaultPrimaryKeyJoinColumns() { + if (this.defaultPrimaryKeyJoinColumn != null) { + return new SingleElementListIterator<OrmPrimaryKeyJoinColumn>(this.defaultPrimaryKeyJoinColumn); + } + return EmptyListIterator.instance(); + } + + protected int defaultPrimaryKeyJoinColumnsSize() { + return (this.defaultPrimaryKeyJoinColumn == null) ? 0 : 1; + } + + public boolean containsSpecifiedPrimaryKeyJoinColumns() { + return !this.specifiedPrimaryKeyJoinColumns.isEmpty(); + } + + public OrmPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn(int index) { + OrmPrimaryKeyJoinColumn oldDefaultPkJoinColumn = this.getDefaultPrimaryKeyJoinColumn(); + if (oldDefaultPkJoinColumn != null) { + //null the default join column now if one already exists. + //if one does not exist, there is already a specified join column. + //Remove it now so that it doesn't get removed during an update and + //cause change notifications to be sent to the UI in the wrong order + this.defaultPrimaryKeyJoinColumn = null; + } + XmlPrimaryKeyJoinColumn resourcePkJoinColumn = OrmFactory.eINSTANCE.createXmlPrimaryKeyJoinColumn(); + OrmPrimaryKeyJoinColumn contextPkJoinColumn = buildPrimaryKeyJoinColumn(resourcePkJoinColumn); + this.specifiedPrimaryKeyJoinColumns.add(index, contextPkJoinColumn); + this.secondaryTable.getPrimaryKeyJoinColumns().add(index, resourcePkJoinColumn); + + this.fireItemAdded(SecondaryTable.SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, index, contextPkJoinColumn); + if (oldDefaultPkJoinColumn != null) { + this.firePropertyChanged(SecondaryTable.DEFAULT_PRIMARY_KEY_JOIN_COLUMN, oldDefaultPkJoinColumn, null); + } + return contextPkJoinColumn; + } + + protected void addSpecifiedPrimaryKeyJoinColumn(int index, OrmPrimaryKeyJoinColumn primaryKeyJoinColumn) { + addItemToList(index, primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SecondaryTable.SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + protected void addSpecifiedPrimaryKeyJoinColumn(OrmPrimaryKeyJoinColumn primaryKeyJoinColumn) { + this.addSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.size(), primaryKeyJoinColumn); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(PrimaryKeyJoinColumn pkJoinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.indexOf(pkJoinColumn)); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(int index) { + OrmPrimaryKeyJoinColumn removedPrimaryKeyJoinColumn = this.specifiedPrimaryKeyJoinColumns.remove(index); + if (!containsSpecifiedPrimaryKeyJoinColumns()) { + //create the defaultJoinColumn now or this will happen during project update + //after removing the join column from the resource model. That causes problems + //in the UI because the change notifications end up in the wrong order. + this.defaultPrimaryKeyJoinColumn = buildPrimaryKeyJoinColumn(null); + } + this.secondaryTable.getPrimaryKeyJoinColumns().remove(index); + fireItemRemoved(SecondaryTable.SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, index, removedPrimaryKeyJoinColumn); + if (this.defaultPrimaryKeyJoinColumn != null) { + //fire change notification if a defaultJoinColumn was created above + this.firePropertyChanged(Entity.DEFAULT_PRIMARY_KEY_JOIN_COLUMN, null, this.defaultPrimaryKeyJoinColumn); + } + } + + protected void removeSpecifiedPrimaryKeyJoinColumn_(OrmPrimaryKeyJoinColumn primaryKeyJoinColumn) { + removeItemFromList(primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SecondaryTable.SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedPrimaryKeyJoinColumn(int targetIndex, int sourceIndex) { + CollectionTools.move(this.specifiedPrimaryKeyJoinColumns, targetIndex, sourceIndex); + this.secondaryTable.getPrimaryKeyJoinColumns().move(targetIndex, sourceIndex); + fireItemMoved(SecondaryTable.SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST, targetIndex, sourceIndex); + } + + + public boolean isVirtual() { + return getOrmEntity().containsVirtualSecondaryTable(this); + } + + @Override + protected XmlSecondaryTable getResourceTable() { + return this.secondaryTable; + } + + @Override + protected XmlSecondaryTable addResourceTable() { + //secondaryTables are part of a collection, the secondary-table element will be removed/added + //when the XmlSecondaryTable is removed/added to the XmlEntity collection + throw new IllegalStateException("resource table is missing"); //$NON-NLS-1$ + } + + @Override + protected void removeResourceTable() { + //secondaryTables are part of a collection, the secondary-table element will be removed/added + //when the XmlSecondaryTable is removed/added to the XmlEntity collection + } + + protected void initialize(XmlSecondaryTable xst) { + this.secondaryTable = xst; + super.initialize(xst); + this.initializeSpecifiedPrimaryKeyJoinColumns(); + this.initializeDefaultPrimaryKeyJoinColumn(); + } + + protected void initializeSpecifiedPrimaryKeyJoinColumns() { + for (XmlPrimaryKeyJoinColumn resourcePkJoinColumn : this.secondaryTable.getPrimaryKeyJoinColumns()) { + this.specifiedPrimaryKeyJoinColumns.add(buildPrimaryKeyJoinColumn(resourcePkJoinColumn)); + } + } + + protected boolean shouldBuildDefaultPrimaryKeyJoinColumn() { + return !containsSpecifiedPrimaryKeyJoinColumns(); + } + + protected void initializeDefaultPrimaryKeyJoinColumn() { + if (!shouldBuildDefaultPrimaryKeyJoinColumn()) { + return; + } + this.defaultPrimaryKeyJoinColumn = buildPrimaryKeyJoinColumn(null); + } + + public void update(XmlSecondaryTable xst) { + this.secondaryTable = xst; + super.update(xst); + this.updateSpecifiedPrimaryKeyJoinColumns(); + this.updateDefaultPrimaryKeyJoinColumn(); + } + + protected void updateSpecifiedPrimaryKeyJoinColumns() { + // make a copy of the XML PK join columns (to prevent ConcurrentModificationException) + Iterator<XmlPrimaryKeyJoinColumn> xmlPkJoinColumns = new CloneIterator<XmlPrimaryKeyJoinColumn>(this.secondaryTable.getPrimaryKeyJoinColumns()); + + for (Iterator<OrmPrimaryKeyJoinColumn> contextPkJoinColumns = this.specifiedPrimaryKeyJoinColumns(); contextPkJoinColumns.hasNext(); ) { + OrmPrimaryKeyJoinColumn contextPkJoinColumn = contextPkJoinColumns.next(); + if (xmlPkJoinColumns.hasNext()) { + contextPkJoinColumn.update(xmlPkJoinColumns.next()); + } + else { + removeSpecifiedPrimaryKeyJoinColumn_(contextPkJoinColumn); + } + } + + while (xmlPkJoinColumns.hasNext()) { + addSpecifiedPrimaryKeyJoinColumn(buildPrimaryKeyJoinColumn(xmlPkJoinColumns.next())); + } + } + + protected void updateDefaultPrimaryKeyJoinColumn() { + if (!shouldBuildDefaultPrimaryKeyJoinColumn()) { + setDefaultPrimaryKeyJoinColumn(null); + return; + } + if (getDefaultPrimaryKeyJoinColumn() == null) { + this.setDefaultPrimaryKeyJoinColumn(buildPrimaryKeyJoinColumn(null)); + } + else { + this.defaultPrimaryKeyJoinColumn.update(null); + } + } + + protected OrmPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(XmlPrimaryKeyJoinColumn resourcePkJoinColumn) { + return getXmlContextNodeFactory().buildOrmPrimaryKeyJoinColumn(this, this.joinColumnOwner, resourcePkJoinColumn); + } + + /** + * a secondary table doesn't have a default name + */ + @Override + protected String buildDefaultName() { + return null; + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + if (this.connectionProfileIsActive()) { + this.validateAgainstDatabase(messages); + } + for (Iterator<OrmPrimaryKeyJoinColumn> stream = this.primaryKeyJoinColumns(); stream.hasNext(); ) { + stream.next().validate(messages, reporter); + } + } + + protected void validateAgainstDatabase(List<IMessage> messages) { + if ( ! this.hasResolvedCatalog()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG, + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange() + ) + ); + return; + } + + if ( ! this.hasResolvedSchema()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA, + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange() + ) + ); + return; + } + + if ( ! this.isResolved()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME, + new String[] {this.getName()}, + this, + this.getNameTextRange() + ) + ); + return; + } + } + + + // ********** pk join column owner adapter ********** + + protected class PrimaryKeyJoinColumnOwner + implements OrmBaseJoinColumn.Owner + { + public TypeMapping getTypeMapping() { + return GenericOrmSecondaryTable.this.getOrmEntity(); + } + + public String getDefaultTableName() { + return GenericOrmSecondaryTable.this.getName(); + } + + public Table getDbTable(String tableName) { + return GenericOrmSecondaryTable.this.getDbTable(); + } + + public Table getReferencedColumnDbTable() { + return getTypeMapping().getPrimaryDbTable(); + } + + public int joinColumnsSize() { + return GenericOrmSecondaryTable.this.primaryKeyJoinColumnsSize(); + } + + public boolean isVirtual(BaseJoinColumn joinColumn) { + return GenericOrmSecondaryTable.this.defaultPrimaryKeyJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + if (joinColumnsSize() != 1) { + return null; + } + Entity parentEntity = getOrmEntity().getParentEntity(); + return (parentEntity == null) ? getOrmEntity().getPrimaryKeyColumnName() : parentEntity.getPrimaryKeyColumnName(); + } + + public TextRange getValidationTextRange() { + return GenericOrmSecondaryTable.this.getValidationTextRange(); + } + + protected boolean isSecondaryTableVirtual() { + return GenericOrmSecondaryTable.this.isVirtual(); + } + + protected String getSecondaryTableName() { + return GenericOrmSecondaryTable.this.getName(); + } + + public IMessage buildUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + if (isSecondaryTableVirtual()) { + return buildVirtualUnresolvedNameMessage(column, textRange); + } + if (((BaseJoinColumn) column).isVirtual()) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getTable()}, + column, + textRange + ); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {column.getName(), column.getTable()}, + column, + textRange + ); + } + + protected IMessage buildVirtualUnresolvedNameMessage(NamedColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] {this.getSecondaryTableName(), column.getName(), column.getDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + if (isSecondaryTableVirtual()) { + return buildVirtualUnresolvedReferencedColumnNameMessage(column, textRange); + } + if (column.isVirtual()) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + protected IMessage buildVirtualUnresolvedReferencedColumnNameMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] {this.getSecondaryTableName(), column.getReferencedColumnName(), column.getReferencedColumnDbTable().getName()}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + if (this.isSecondaryTableVirtual()) { + return this.buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.getSecondaryTableName()}, + column, + textRange + ); + } + + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + if (this.isSecondaryTableVirtual()) { + return this.buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(column, textRange); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[0], + column, + textRange + ); + } + + protected IMessage buildVirtualUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(BaseJoinColumn column, TextRange textRange) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.getSecondaryTableName()}, + column, + textRange + ); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java new file mode 100644 index 0000000000..a7805c1564 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmSequenceGenerator; +import org.eclipse.jpt.core.resource.orm.XmlSequenceGenerator; + +/** + * + */ +public class GenericOrmSequenceGenerator + extends AbstractOrmSequenceGenerator +{ + + public GenericOrmSequenceGenerator(XmlContextNode parent, XmlSequenceGenerator resourceSequenceGenerator) { + super(parent, resourceSequenceGenerator); + } + + // ********** database stuff ********** + + /** + * The JPA spec does not allow a sequence to have a schema. + */ + @Override + protected String getSchema() { + return this.getContextDefaultSchema(); + } + + /** + * The JPA spec does not allow a sequence to have a catalog. + */ + @Override + protected String getCatalog() { + return this.getContextDefaultCatalog(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java new file mode 100644 index 0000000000..63fcf35496 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTable.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.core.context.orm.OrmEntity; +import org.eclipse.jpt.core.context.orm.OrmTable; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmTable; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlEntity; +import org.eclipse.jpt.core.resource.orm.XmlTable; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * + */ +public class GenericOrmTable + extends AbstractOrmTable + implements OrmTable +{ + protected XmlEntity resourceEntity; + + public GenericOrmTable(OrmEntity parent) { + super(parent); + } + + public OrmEntity getOrmEntity() { + return (OrmEntity) super.getParent(); + } + + @Override + protected XmlTable getResourceTable() { + return this.resourceEntity.getTable(); + } + + @Override + protected XmlTable addResourceTable() { + XmlTable resourceTable = OrmFactory.eINSTANCE.createXmlTable(); + this.resourceEntity.setTable(resourceTable); + return resourceTable; + } + + @Override + protected void removeResourceTable() { + this.resourceEntity.setTable(null); + } + + public void initialize(XmlEntity xmlEntity) { + this.resourceEntity = xmlEntity; + this.initialize(this.getResourceTable()); + } + + public void update(XmlEntity xmlEntity) { + this.resourceEntity = xmlEntity; + this.update(this.getResourceTable()); + } + + @Override + protected String buildDefaultName() { + return this.getOrmEntity().getDefaultTableName(); + } + + @Override + protected String buildDefaultSchema() { + return this.getOrmEntity().getDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getOrmEntity().getDefaultCatalog(); + } + + //*********** Validation ******************************* + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + if (this.connectionProfileIsActive()) { + this.validateAgainstDatabase(messages); + } + } + + protected void validateAgainstDatabase(List<IMessage> messages) { + if ( ! this.hasResolvedCatalog()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_CATALOG, + new String[] {this.getCatalog(), this.getName()}, + this, + this.getCatalogTextRange() + ) + ); + return; + } + + if ( ! this.hasResolvedSchema()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA, + new String[] {this.getSchema(), this.getName()}, + this, + this.getSchemaTextRange() + ) + ); + return; + } + + if ( ! this.isResolved()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TABLE_UNRESOLVED_NAME, + new String[] {this.getName()}, + this, + this.getNameTextRange() + ) + ); + return; + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java new file mode 100644 index 0000000000..f9910b4661 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jpt.core.context.TableGenerator; +import org.eclipse.jpt.core.context.UniqueConstraint; +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmTableGenerator; +import org.eclipse.jpt.core.context.orm.OrmUniqueConstraint; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmGenerator; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlTableGenerator; +import org.eclipse.jpt.core.resource.orm.XmlUniqueConstraint; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.Table; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneIterator; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; +import org.eclipse.jpt.utility.internal.iterators.EmptyIterator; + +/** + * + */ +public class GenericOrmTableGenerator + extends AbstractOrmGenerator<XmlTableGenerator> + implements OrmTableGenerator, UniqueConstraint.Owner +{ + protected String specifiedTable; + protected String defaultTable; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedSchema; + protected String defaultSchema; + + protected String specifiedPkColumnName; + protected String defaultPkColumnName; + + protected String specifiedValueColumnName; + protected String defaultValueColumnName; + + protected String specifiedPkColumnValue; + protected String defaultPkColumnValue; + + protected final List<OrmUniqueConstraint> uniqueConstraints; + + + // ********** constructor ********** + + public GenericOrmTableGenerator(XmlContextNode parent, XmlTableGenerator resourceTableGenerator) { + super(parent); + this.uniqueConstraints = new ArrayList<OrmUniqueConstraint>(); + this.initialize(resourceTableGenerator); + } + + @Override + public int getDefaultInitialValue() { + return TableGenerator.DEFAULT_INITIAL_VALUE; + } + + // ********** table ********** + + public String getTable() { + return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable; + } + + public String getSpecifiedTable() { + return this.specifiedTable; + } + + public void setSpecifiedTable(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.getResourceGenerator().setTable(table); + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + protected void setSpecifiedTable_(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + public String getDefaultTable() { + return this.defaultTable; + } + + protected void setDefaultTable(String table) { + String old = this.defaultTable; + this.defaultTable = table; + this.firePropertyChanged(DEFAULT_TABLE_PROPERTY, old, table); + } + + + // ********** schema ********** + + @Override + public String getSchema() { + return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema; + } + + public String getSpecifiedSchema() { + return this.specifiedSchema; + } + + public void setSpecifiedSchema(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.getResourceGenerator().setSchema(schema); + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + public String getDefaultSchema() { + return this.defaultSchema; + } + + protected void setDefaultSchema(String schema) { + String old = this.defaultSchema; + this.defaultSchema = schema; + this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema); + } + + + // ********** catalog ********** + + @Override + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.getResourceGenerator().setCatalog(catalog); + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + public String getDefaultCatalog() { + return this.defaultCatalog; + } + + protected void setDefaultCatalog(String catalog) { + String old = this.defaultCatalog; + this.defaultCatalog = catalog; + firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog); + } + + + // ********** primary key column name ********** + + public String getPkColumnName() { + return (this.specifiedPkColumnName != null) ? this.specifiedPkColumnName : this.defaultPkColumnName; + } + + public String getSpecifiedPkColumnName() { + return this.specifiedPkColumnName; + } + + public void setSpecifiedPkColumnName(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.getResourceGenerator().setPkColumnName(name); + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + protected void setSpecifiedPkColumnName_(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultPkColumnName() { + return this.defaultPkColumnName; + } + + protected void setDefaultPkColumnName(String name) { + String old = this.defaultPkColumnName; + this.defaultPkColumnName = name; + this.firePropertyChanged(DEFAULT_PK_COLUMN_NAME_PROPERTY, old, name); + } + + + // ********** value column name ********** + + public String getValueColumnName() { + return (this.specifiedValueColumnName != null) ? this.specifiedValueColumnName : this.defaultValueColumnName; + } + + public String getSpecifiedValueColumnName() { + return this.specifiedValueColumnName; + } + + public void setSpecifiedValueColumnName(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.getResourceGenerator().setValueColumnName(name); + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + protected void setSpecifiedValueColumnName_(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultValueColumnName() { + return this.defaultValueColumnName; + } + + protected void setDefaultValueColumnName(String name) { + String old = this.defaultValueColumnName; + this.defaultValueColumnName = name; + this.firePropertyChanged(DEFAULT_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + + // ********** primary key column value ********** + + public String getPkColumnValue() { + return (this.specifiedPkColumnValue != null) ? this.specifiedPkColumnValue : this.defaultPkColumnValue; + } + + public String getSpecifiedPkColumnValue() { + return this.specifiedPkColumnValue; + } + + public void setSpecifiedPkColumnValue(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.getResourceGenerator().setPkColumnValue(value); + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + protected void setSpecifiedPkColumnValue_(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + public String getDefaultPkColumnValue() { + return this.defaultPkColumnValue; + } + + public void setDefaultPkColumnValue(String value) { + String old = this.defaultPkColumnValue; + this.defaultPkColumnValue = value; + this.firePropertyChanged(DEFAULT_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + + // ********** unique constraints ********** + + public ListIterator<OrmUniqueConstraint> uniqueConstraints() { + return new CloneListIterator<OrmUniqueConstraint>(this.uniqueConstraints); + } + + public int uniqueConstraintsSize() { + return this.uniqueConstraints.size(); + } + + public OrmUniqueConstraint addUniqueConstraint(int index) { + XmlUniqueConstraint resourceUC = OrmFactory.eINSTANCE.createXmlUniqueConstraint(); + OrmUniqueConstraint contextUC = this.buildUniqueConstraint(resourceUC); + this.uniqueConstraints.add(index, contextUC); + this.getResourceGenerator().getUniqueConstraints().add(index, resourceUC); + this.fireItemAdded(UNIQUE_CONSTRAINTS_LIST, index, contextUC); + return contextUC; + } + + protected void addUniqueConstraint(int index, OrmUniqueConstraint uniqueConstraint) { + this.addItemToList(index, uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + protected void addUniqueConstraint(OrmUniqueConstraint uniqueConstraint) { + this.addUniqueConstraint(this.uniqueConstraints.size(), uniqueConstraint); + } + + public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) { + this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + public void removeUniqueConstraint(int index) { + OrmUniqueConstraint uniqueConstraint = this.uniqueConstraints.remove(index); + this.getResourceGenerator().getUniqueConstraints().remove(index); + this.fireItemRemoved(UNIQUE_CONSTRAINTS_LIST, index, uniqueConstraint); + } + + protected void removeUniqueConstraint_(OrmUniqueConstraint uniqueConstraint) { + this.removeItemFromList(uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + public void moveUniqueConstraint(int targetIndex, int sourceIndex) { + CollectionTools.move(this.uniqueConstraints, targetIndex, sourceIndex); + this.getResourceGenerator().getUniqueConstraints().move(targetIndex, sourceIndex); + this.fireItemMoved(UNIQUE_CONSTRAINTS_LIST, targetIndex, sourceIndex); + } + + + //******************* UniqueConstraint.Owner implementation ****************** + + public Iterator<String> candidateUniqueConstraintColumnNames() { + org.eclipse.jpt.db.Table dbTable = this.getDbTable(); + return (dbTable != null) ? dbTable.getSortedColumnIdentifiers().iterator() : EmptyIterator.<String>instance(); + } + + + // ********** resource => context ********** + + @Override + protected void initialize(XmlTableGenerator xmlTableGenerator) { + super.initialize(xmlTableGenerator); + this.specifiedTable = xmlTableGenerator.getTable(); + this.defaultSchema = this.buildDefaultSchema(); + this.specifiedSchema = xmlTableGenerator.getSchema(); + this.defaultCatalog = this.buildDefaultCatalog(); + this.specifiedCatalog = xmlTableGenerator.getCatalog(); + this.specifiedPkColumnName = xmlTableGenerator.getPkColumnName(); + this.specifiedValueColumnName = xmlTableGenerator.getValueColumnName(); + this.specifiedPkColumnValue = xmlTableGenerator.getPkColumnValue(); + this.initializeUniqueContraints(); + } + + protected void initializeUniqueContraints() { + if (this.resourceGenerator == null) { + return; + } + for (XmlUniqueConstraint uniqueConstraint : this.resourceGenerator.getUniqueConstraints()) { + this.uniqueConstraints.add(this.buildUniqueConstraint(uniqueConstraint)); + } + } + + @Override + public void update(XmlTableGenerator xmlTableGenerator) { + super.update(xmlTableGenerator); + this.setSpecifiedTable_(xmlTableGenerator.getTable()); + this.setDefaultSchema(this.buildDefaultSchema()); + this.setSpecifiedSchema_(xmlTableGenerator.getSchema()); + this.setDefaultCatalog(this.buildDefaultCatalog()); + this.setSpecifiedCatalog_(xmlTableGenerator.getCatalog()); + this.setSpecifiedPkColumnName_(xmlTableGenerator.getPkColumnName()); + this.setSpecifiedValueColumnName_(xmlTableGenerator.getValueColumnName()); + this.setSpecifiedPkColumnValue_(xmlTableGenerator.getPkColumnValue()); + // TODO defaults + this.updateUniqueConstraints(); + } + + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + protected void updateUniqueConstraints() { + Iterator<XmlUniqueConstraint> xmlConstraints = this.xmlUniqueConstraints(); + + for (Iterator<OrmUniqueConstraint> contextConstraints = this.uniqueConstraints(); contextConstraints.hasNext(); ) { + OrmUniqueConstraint contextConstraint = contextConstraints.next(); + if (xmlConstraints.hasNext()) { + contextConstraint.update(xmlConstraints.next()); + } + else { + this.removeUniqueConstraint_(contextConstraint); + } + } + + while (xmlConstraints.hasNext()) { + this.addUniqueConstraint(this.buildUniqueConstraint(xmlConstraints.next())); + } + } + + protected Iterator<XmlUniqueConstraint> xmlUniqueConstraints() { + // make a copy of the XML constraints (to prevent ConcurrentModificationException) + return (this.resourceGenerator == null) ? EmptyIterator.<XmlUniqueConstraint>instance() + : new CloneIterator<XmlUniqueConstraint>(this.resourceGenerator.getUniqueConstraints()); + } + + protected OrmUniqueConstraint buildUniqueConstraint(XmlUniqueConstraint resourceUniqueConstraint) { + return this.getXmlContextNodeFactory().buildOrmUniqueConstraint(this, this, resourceUniqueConstraint); + } + + + // ********** database stuff ********** + + public Table getDbTable() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getTable()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java new file mode 100644 index 0000000000..8adc7a5953 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.Converter; +import org.eclipse.jpt.core.context.TemporalConverter; +import org.eclipse.jpt.core.context.TemporalType; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmConverter; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlConvertibleMapping; +import org.eclipse.jpt.core.utility.TextRange; + +public class GenericOrmTemporalConverter extends AbstractOrmXmlContextNode + implements TemporalConverter, OrmConverter +{ + protected TemporalType temporalType; + + protected XmlConvertibleMapping resourceConvertibleMapping; + + public GenericOrmTemporalConverter(OrmAttributeMapping parent, XmlConvertibleMapping resourceConvertableMapping) { + super(parent); + this.initialize(resourceConvertableMapping); + } + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + public String getType() { + return Converter.TEMPORAL_CONVERTER; + } + + public TemporalType getTemporalType() { + return this.temporalType; + } + + public void setTemporalType(TemporalType newTemporalType) { + TemporalType oldTemporalType = this.temporalType; + this.temporalType = newTemporalType; + this.resourceConvertibleMapping.setTemporal(TemporalType.toOrmResourceModel(newTemporalType)); + firePropertyChanged(TEMPORAL_TYPE_PROPERTY, oldTemporalType, newTemporalType); + } + + protected void setTemporalType_(TemporalType newTemporalType) { + TemporalType oldTemporalType = this.temporalType; + this.temporalType = newTemporalType; + firePropertyChanged(TEMPORAL_TYPE_PROPERTY, oldTemporalType, newTemporalType); + } + + + protected void initialize(XmlConvertibleMapping resourceConvertibleMapping) { + this.resourceConvertibleMapping = resourceConvertibleMapping; + this.temporalType = this.temporalType(); + } + + public void update() { + this.setTemporalType_(this.temporalType()); + } + + protected TemporalType temporalType() { + return TemporalType.fromOrmResourceModel(this.resourceConvertibleMapping.getTemporal()); + } + + + public TextRange getValidationTextRange() { + return this.resourceConvertibleMapping.getTemporalTextRange(); + } + + public void addToResourceModel() { + this.resourceConvertibleMapping.setTemporal(org.eclipse.jpt.core.resource.orm.TemporalType.DATE); + } + + public void removeFromResourceModel() { + this.resourceConvertibleMapping.setTemporal(null); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java new file mode 100644 index 0000000000..be02c1fa29 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.MappingKeys; +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.context.orm.OrmTransientMapping; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.XmlTransient; + + +public class GenericOrmTransientMapping + extends AbstractOrmAttributeMapping<XmlTransient> + implements OrmTransientMapping +{ + + public GenericOrmTransientMapping(OrmPersistentAttribute parent, XmlTransient resourceMapping) { + super(parent, resourceMapping); + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmTransientMapping(this); + } + + public int getXmlSequence() { + return 90; + } + + public String getKey() { + return MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY; + } + + public void addToResourceModel(Attributes resourceAttributes) { + resourceAttributes.getTransients().add(this.resourceAttributeMapping); + } + + public void removeFromResourceModel(Attributes resourceAttributes) { + resourceAttributes.getTransients().remove(this.resourceAttributeMapping); + } + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java new file mode 100644 index 0000000000..6eb27d552f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jpt.core.context.XmlContextNode; +import org.eclipse.jpt.core.context.orm.OrmUniqueConstraint; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlUniqueConstraint; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.CollectionTools; +import org.eclipse.jpt.utility.internal.iterators.CloneListIterator; + +public class GenericOrmUniqueConstraint + extends AbstractOrmXmlContextNode + implements OrmUniqueConstraint +{ + + protected final List<String> columnNames; + + protected XmlUniqueConstraint resourceUniqueConstraint; + + protected Owner owner; + + public GenericOrmUniqueConstraint(XmlContextNode parent, Owner owner, XmlUniqueConstraint resourceUniqueConstraint) { + super(parent); + this.owner = owner; + this.columnNames = new ArrayList<String>(); + this.initialize(resourceUniqueConstraint); + } + + public ListIterator<String> columnNames() { + return new CloneListIterator<String>(this.columnNames); + } + + public int columnNamesSize() { + return this.columnNames.size(); + } + + public void addColumnName(int index, String columnName) { + this.columnNames.add(index, columnName); + this.resourceUniqueConstraint.getColumnNames().add(index, columnName); + fireItemAdded(COLUMN_NAMES_LIST, index, columnName); + } + + protected void addColumnName_(int index, String columnName) { + this.addItemToList(index, columnName, this.columnNames, COLUMN_NAMES_LIST); + } + + protected void addColumnName_(String columnName) { + this.addItemToList(columnName, this.columnNames, COLUMN_NAMES_LIST); + } + + protected void setColumnName_(int index, String columnName) { + this.setItemInList(index, columnName, this.columnNames, COLUMN_NAMES_LIST); + } + + public void removeColumnName(String columnName) { + this.removeColumnName(this.columnNames.indexOf(columnName)); + } + + public void removeColumnName(int index) { + String removedColumnName = this.columnNames.remove(index); + this.resourceUniqueConstraint.getColumnNames().remove(index); + fireItemRemoved(COLUMN_NAMES_LIST, index, removedColumnName); + } + + protected void removeColumnName_(int index) { + this.removeItemFromList(index, this.columnNames, COLUMN_NAMES_LIST); + } + + public void moveColumnName(int targetIndex, int sourceIndex) { + CollectionTools.move(this.columnNames, targetIndex, sourceIndex); + this.resourceUniqueConstraint.getColumnNames().move(targetIndex, sourceIndex); + fireItemMoved(COLUMN_NAMES_LIST, targetIndex, sourceIndex); + } + + public TextRange getValidationTextRange() { + return this.resourceUniqueConstraint.getValidationTextRange(); + } + + protected void initialize(XmlUniqueConstraint xmlUniqueConstraint) { + this.resourceUniqueConstraint = xmlUniqueConstraint; + this.initializeColumnNames(); + } + + protected void initializeColumnNames() { + for (String annotationColumnName : this.resourceUniqueConstraint.getColumnNames()) { + this.columnNames.add(annotationColumnName); + } + } + + public void update(XmlUniqueConstraint xmlUniqueConstraint) { + this.resourceUniqueConstraint = xmlUniqueConstraint; + this.updateColumnNames(); + } + + protected void updateColumnNames() { + int index = 0; + for (String xmlColumnName : this.resourceUniqueConstraint.getColumnNames()) { + if (this.columnNames.size() > index) { + if ( ! this.columnNames.get(index).equals(xmlColumnName)) { + this.setColumnName_(index, xmlColumnName); + } + } + else { + this.addColumnName_(xmlColumnName); + } + index++; + } + + while (index < this.columnNames.size()) { + this.removeColumnName_(index); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java new file mode 100644 index 0000000000..0d74de740f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmVersionMapping; +import org.eclipse.jpt.core.resource.orm.XmlVersion; + + +public class GenericOrmVersionMapping extends AbstractOrmVersionMapping<XmlVersion> +{ + + public GenericOrmVersionMapping(OrmPersistentAttribute parent, XmlVersion resourceMapping) { + super(parent, resourceMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXml.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXml.java new file mode 100644 index 0000000000..9b39249296 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXml.java @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.core.JpaFile; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.MappingFileRoot; +import org.eclipse.jpt.core.context.PersistentType; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.context.orm.EntityMappings; +import org.eclipse.jpt.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.core.context.orm.OrmXml; +import org.eclipse.jpt.core.context.persistence.MappingFileRef; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.XmlEntityMappings; +import org.eclipse.jpt.core.resource.xml.JpaXmlResource; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * JPA <code>orm.xml</code> file. + */ +public class GenericOrmXml + extends AbstractOrmXmlContextNode + implements OrmXml +{ + /** + * If the XML resource's content type changes, the mapping file + * ref will dispose its current mapping file and build a new one. + */ + protected final JpaXmlResource xmlResource; + + /** + * The resouce type will only change if the XML file's version changes + * (since, if the content type changes, we get garbage-collected). + */ + protected JpaResourceType resourceType; + + protected EntityMappings entityMappings; + + + public GenericOrmXml(MappingFileRef parent, JpaXmlResource xmlResource) { + super(parent); + this.checkXmlResource(xmlResource); + this.xmlResource = xmlResource; + this.resourceType = xmlResource.getResourceType(); + + XmlEntityMappings xmlEntityMappings = (XmlEntityMappings) xmlResource.getRootObject(); + if (xmlEntityMappings != null) { + this.entityMappings = this.buildEntityMappings(xmlEntityMappings); + } + } + + protected void checkXmlResource(JpaXmlResource resource) { + if (resource == null) { + throw new NullPointerException(); + } + if ( ! resource.getContentType().isKindOf(JptCorePlugin.MAPPING_FILE_CONTENT_TYPE)) { + throw new IllegalArgumentException("Content type is not 'mapping file': " + resource); //$NON-NLS-1$ + } + } + + // ********** overrides ********** + + @Override + public MappingFileRef getParent() { + return (MappingFileRef) super.getParent(); + } + + @Override + public IResource getResource() { + return this.xmlResource.getFile(); + } + + @Override + public JpaResourceType getResourceType() { + return this.resourceType; + } + + // ********** JpaStructureNode implementation ********** + + public String getId() { + // isn't actually displayed, so needs no details page + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + if ((this.entityMappings != null) && this.entityMappings.containsOffset(textOffset)) { + return this.entityMappings.getStructureNode(textOffset); + } + return this; + } + + // never actually selected + public TextRange getSelectionTextRange() { + return TextRange.Empty.instance(); + } + + public void dispose() { + if (this.entityMappings != null) { + this.entityMappings.dispose(); + } + JpaFile jpaFile = getJpaFile(); + if (jpaFile != null) { + jpaFile.removeRootStructureNode(this.xmlResource); + } + } + + // ********** MappingFile implementation ********** + + public JpaXmlResource getXmlResource() { + return this.xmlResource; + } + + public MappingFileRoot getRoot() { + return this.entityMappings; + } + + public OrmPersistentType getPersistentType(String name) { + return (this.entityMappings == null) ? null : this.entityMappings.getPersistentType(name); + } + + // ********** PersistentTypeContainer implementation ********** + + /** + * All orm.xml mapping files must be able to generate a static metamodel + * because 1.0 orm.xml files can be referenced from 2.0 persistence.xml + * files. + */ + public Iterable<? extends PersistentType> getPersistentTypes() { + return (this.entityMappings != null) ? this.entityMappings.getPersistentTypes() : EmptyIterable.<JavaPersistentType> instance(); + } + + // ********** entity mappings ********** + + public EntityMappings getEntityMappings() { + return this.entityMappings; + } + + protected void setEntityMappings(EntityMappings entityMappings) { + EntityMappings old = this.entityMappings; + this.entityMappings = entityMappings; + this.firePropertyChanged(ENTITY_MAPPINGS_PROPERTY, old, entityMappings); + } + + protected EntityMappings buildEntityMappings(XmlEntityMappings xmlEntityMappings) { + return this.getXmlContextNodeFactory().buildEntityMappings(this, xmlEntityMappings); + } + + // ********** updating ********** + + public void update() { + XmlEntityMappings oldXmlEntityMappings = (this.entityMappings == null) ? null : this.entityMappings.getXmlEntityMappings(); + XmlEntityMappings newXmlEntityMappings = (XmlEntityMappings) this.xmlResource.getRootObject(); + JpaResourceType newResourceType = this.xmlResource.getResourceType(); + + // If the old and new xml entity mappings are different instances, + // we scrap the old context entity mappings and rebuild. This can + // happen when the resource model drastically changes, such as + // a cvs checkout or an edit reversion. + if ((oldXmlEntityMappings != newXmlEntityMappings) + || (newXmlEntityMappings == null) + || this.valuesAreDifferent(this.resourceType, newResourceType)) { + + if (this.entityMappings != null) { + getJpaFile().removeRootStructureNode(this.xmlResource); + this.entityMappings.dispose(); + setEntityMappings(null); + } + } + + this.resourceType = newResourceType; + + if (newXmlEntityMappings != null) { + if (this.entityMappings != null) { + this.entityMappings.update(); + } + else { + setEntityMappings(buildEntityMappings(newXmlEntityMappings)); + } + + this.getJpaFile().addRootStructureNode(this.xmlResource, this.entityMappings); + } + } + + protected JpaFile getJpaFile() { + return this.getJpaFile(this.xmlResource.getFile()); + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.entityMappings != null) { + this.entityMappings.postUpdate(); + } + } + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return TextRange.Empty.instance(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + if (this.entityMappings != null) { + this.entityMappings.validate(messages, reporter); + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java new file mode 100644 index 0000000000..d6b52f3704 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.orm.NullOrmAttributeMappingDefinition; +import org.eclipse.jpt.core.context.orm.OrmAttributeMappingDefinition; +import org.eclipse.jpt.core.context.orm.OrmTypeMappingDefinition; +import org.eclipse.jpt.core.context.orm.OrmXmlContextNodeFactory; +import org.eclipse.jpt.core.context.orm.OrmXmlDefinition; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlDefinition; +import org.eclipse.jpt.core.internal.context.orm.GenericOrmXmlContextNodeFactory; +import org.eclipse.jpt.core.internal.context.orm.OrmBasicMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmEmbeddableDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmEmbeddedIdMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmEmbeddedMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmEntityDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmIdMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmManyToManyMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmManyToOneMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmMappedSuperclassDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmOneToManyMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmOneToOneMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmTransientMappingDefinition; +import org.eclipse.jpt.core.internal.context.orm.OrmVersionMappingDefinition; +import org.eclipse.jpt.core.resource.orm.OrmFactory; + +public class GenericOrmXmlDefinition + extends AbstractOrmXmlDefinition +{ + // singleton + private static final OrmXmlDefinition INSTANCE = + new GenericOrmXmlDefinition(); + + + /** + * Return the singleton + */ + public static OrmXmlDefinition instance() { + return INSTANCE; + } + + + /** + * Enforce singleton usage + */ + private GenericOrmXmlDefinition() { + super(); + } + + + public EFactory getResourceNodeFactory() { + return OrmFactory.eINSTANCE; + } + + @Override + protected OrmXmlContextNodeFactory buildContextNodeFactory() { + return new GenericOrmXmlContextNodeFactory(); + } + + public JpaResourceType getResourceType() { + return JptCorePlugin.ORM_XML_1_0_RESOURCE_TYPE; + } + + + // ********** ORM type mappings ********** + + @Override + protected OrmTypeMappingDefinition[] buildOrmTypeMappingDefinitions() { + // order should not matter here, but we'll use the same order as for java + // (@see {@link GenericJpaPlatformProvider}) + return new OrmTypeMappingDefinition[] { + OrmEntityDefinition.instance(), + OrmEmbeddableDefinition.instance(), + OrmMappedSuperclassDefinition.instance()}; + } + + + // ********** ORM attribute mappings ********** + + @Override + protected OrmAttributeMappingDefinition[] buildOrmAttributeMappingDefinitions() { + // order should not matter here, but we'll use the same order as for java + // (@see {@link GenericJpaPlatformProvider}) + return new OrmAttributeMappingDefinition[] { + OrmTransientMappingDefinition.instance(), + OrmIdMappingDefinition.instance(), + OrmVersionMappingDefinition.instance(), + OrmBasicMappingDefinition.instance(), + OrmEmbeddedMappingDefinition.instance(), + OrmEmbeddedIdMappingDefinition.instance(), + OrmManyToManyMappingDefinition.instance(), + OrmManyToOneMappingDefinition.instance(), + OrmOneToManyMappingDefinition.instance(), + OrmOneToOneMappingDefinition.instance(), + NullOrmAttributeMappingDefinition.instance()}; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitDefaults.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitDefaults.java new file mode 100644 index 0000000000..503f5aba6c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitDefaults.java @@ -0,0 +1,324 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0, which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.orm.PersistenceUnitMetadata; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.jpa2.context.orm.OrmPersistenceUnitDefaults2_0; +import org.eclipse.jpt.core.resource.orm.OrmFactory; +import org.eclipse.jpt.core.resource.orm.XmlEntityMappings; +import org.eclipse.jpt.core.resource.orm.XmlPersistenceUnitDefaults; +import org.eclipse.jpt.core.resource.orm.XmlPersistenceUnitMetadata; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Catalog; +import org.eclipse.jpt.db.Schema; +import org.eclipse.jpt.db.SchemaContainer; + +/** + * <code>orm.xml</code> file + * <br> + * <code>persistence-unit-defaults</code> element + */ +public class GenericPersistenceUnitDefaults + extends AbstractOrmXmlContextNode + implements OrmPersistenceUnitDefaults2_0 +{ + protected AccessType access; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedSchema; + protected String defaultSchema; + + protected boolean cascadePersist; + protected boolean delimitedIdentifiers; + + + // ********** constructor/initialization ********** + + public GenericPersistenceUnitDefaults(PersistenceUnitMetadata parent) { + super(parent); + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + if (xmlDefaults != null) { + this.access = AccessType.fromOrmResourceModel(xmlDefaults.getAccess()); + this.specifiedCatalog = xmlDefaults.getCatalog(); + this.specifiedSchema = xmlDefaults.getSchema(); + this.cascadePersist = xmlDefaults.isCascadePersist(); + this.delimitedIdentifiers = xmlDefaults.isDelimitedIdentifiers(); + } + this.defaultCatalog = this.getJpaProject().getDefaultCatalog(); + this.defaultSchema = this.getJpaProject().getDefaultSchema(); + } + + public boolean resourceExists() { + return this.getXmlDefaults() != null; + } + + @Override + public PersistenceUnitMetadata getParent() { + return (PersistenceUnitMetadata) super.getParent(); + } + + protected XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadata() { + return this.getParent().getXmlPersistenceUnitMetadata(); + } + + protected XmlEntityMappings getXmlEntityMappings() { + return this.getParent().getXmlEntityMappings(); + } + + // ********** access ********** + + public AccessType getAccess() { + return this.access; + } + + public void setAccess(AccessType access) { + AccessType old = this.access; + this.access = access; + if (access != old) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + xmlDefaults.setAccess(AccessType.toOrmResourceModel(access)); + this.checkXmlDefaults(xmlDefaults); + this.firePropertyChanged(ACCESS_PROPERTY, old, access); + } + } + + protected void setAccess_(AccessType access) { + AccessType old = this.access; + this.access = access; + this.firePropertyChanged(ACCESS_PROPERTY, old, access); + } + + + // ********** schema container ********** + + /** + * If we don't have a catalog (i.e. we don't even have a <em>default</em> catalog), + * then the database probably does not support catalogs; and we need to + * get the schema directly from the database. + */ + public SchemaContainer getDbSchemaContainer() { + String catalog = this.getCatalog(); + return (catalog != null) ? this.getDbCatalog(catalog) : this.getDatabase(); + } + + + // ********** catalog ********** + + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + if (this.attributeValueHasChanged(old, catalog)) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + xmlDefaults.setCatalog(catalog); + this.checkXmlDefaults(xmlDefaults); + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + public String getDefaultCatalog() { + return this.defaultCatalog; + } + + protected void setDefaultCatalog(String catalog) { + String old = this.defaultCatalog; + this.defaultCatalog = catalog; + this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog); + } + + /** + * If we don't have a catalog (i.e. we don't even have a <em>default</em> + * catalog), then the database probably does not support catalogs. + */ + public Catalog getDbCatalog() { + String catalog = this.getCatalog(); + return (catalog == null) ? null : this.getDbCatalog(catalog); + } + + + // ********** schema ********** + + public String getSchema() { + return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema; + } + + public String getSpecifiedSchema() { + return this.specifiedSchema; + } + + public void setSpecifiedSchema(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + if (this.attributeValueHasChanged(old, schema)) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + xmlDefaults.setSchema(schema); + this.checkXmlDefaults(xmlDefaults); + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + public String getDefaultSchema() { + return this.defaultSchema; + } + + protected void setDefaultSchema(String schema) { + String old = this.defaultSchema; + this.defaultSchema = schema; + this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema); + } + + public Schema getDbSchema() { + SchemaContainer dbSchemaContainer = this.getDbSchemaContainer(); + return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema()); + } + + + // ********** cascade persist ********** + + public boolean isCascadePersist() { + return this.cascadePersist; + } + + public void setCascadePersist(boolean cascadePersist) { + boolean old = this.cascadePersist; + this.cascadePersist = cascadePersist; + if (cascadePersist != old) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + xmlDefaults.setCascadePersist(cascadePersist); + this.checkXmlDefaults(xmlDefaults); + this.firePropertyChanged(CASCADE_PERSIST_PROPERTY, old, cascadePersist); + } + } + + protected void setCascadePersist_(boolean cp) { + boolean old = this.cascadePersist; + this.cascadePersist = cp; + this.firePropertyChanged(CASCADE_PERSIST_PROPERTY, old, cp); + } + + + // ********** delimited identifiers ********** + + public boolean isDelimitedIdentifiers() { + return this.delimitedIdentifiers; + } + + public void setDelimitedIdentifiers(boolean delimitedIdentifiers) { + boolean old = this.delimitedIdentifiers; + this.delimitedIdentifiers = delimitedIdentifiers; + if (delimitedIdentifiers != old) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + xmlDefaults.setDelimitedIdentifiers(delimitedIdentifiers); + this.checkXmlDefaults(xmlDefaults); + this.firePropertyChanged(DELIMITED_IDENTIFIERS_PROPERTY, old, delimitedIdentifiers); + } + } + + protected void setDelimitedIdentifiers_(boolean di) { + boolean old = this.delimitedIdentifiers; + this.delimitedIdentifiers = di; + this.firePropertyChanged(DELIMITED_IDENTIFIERS_PROPERTY, old, di); + } + + + // ********** behavior ********** + + /** + * If the XML does not exist, build it before returning it + */ + protected XmlPersistenceUnitDefaults getXmlDefaultsForUpdate() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults != null) ? xmlDefaults : this.buildXmlDefaults(); + } + + /** + * build the XML defaults and the XML metadata if necessary + */ + protected XmlPersistenceUnitDefaults buildXmlDefaults() { + XmlPersistenceUnitMetadata resourceMetadata = this.getXmlPersistenceUnitMetadata(); + if (resourceMetadata == null) { + resourceMetadata = this.buildXmlPersistenceUnitMetadata(); + this.getXmlEntityMappings().setPersistenceUnitMetadata(resourceMetadata); + } + XmlPersistenceUnitDefaults xmlDefaults = OrmFactory.eINSTANCE.createXmlPersistenceUnitDefaults(); + resourceMetadata.setPersistenceUnitDefaults(xmlDefaults); + return xmlDefaults; + } + + protected XmlPersistenceUnitMetadata buildXmlPersistenceUnitMetadata() { + return this.getParent().buildXmlPersistenceUnitMetadata(); + } + + /** + * clear the resource defaults and the resource metadata if appropriate + */ + protected void checkXmlDefaults(XmlPersistenceUnitDefaults xmlDefaults) { + if (xmlDefaults.isUnset()) { + XmlPersistenceUnitMetadata metadata = this.getXmlEntityMappings().getPersistenceUnitMetadata(); + metadata.setPersistenceUnitDefaults(null); + if (metadata.isUnset()) { + this.getXmlEntityMappings().setPersistenceUnitMetadata(null); + } + } + } + + public void update() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + if (xmlDefaults == null) { + this.setAccess_(null); + this.setSpecifiedCatalog_(null); + this.setSpecifiedSchema_(null); + this.setCascadePersist_(false); + this.setDelimitedIdentifiers_(false); + } else { + this.setAccess_(AccessType.fromOrmResourceModel(xmlDefaults.getAccess())); + this.setSpecifiedCatalog_(xmlDefaults.getCatalog()); + this.setSpecifiedSchema_(xmlDefaults.getSchema()); + this.setCascadePersist_(xmlDefaults.isCascadePersist()); + this.setDelimitedIdentifiers_(xmlDefaults.isDelimitedIdentifiers()); + } + this.setDefaultCatalog(this.getJpaProject().getDefaultCatalog()); + this.setDefaultSchema(this.getJpaProject().getDefaultSchema()); + } + + public TextRange getValidationTextRange() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults != null) ? xmlDefaults.getValidationTextRange() : this.getXmlEntityMappings().getValidationTextRange(); + } + + protected XmlPersistenceUnitDefaults getXmlDefaults() { + XmlPersistenceUnitMetadata metadata = this.getXmlPersistenceUnitMetadata(); + return (metadata == null) ? null : metadata.getPersistenceUnitDefaults(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitMetadata.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitMetadata.java new file mode 100644 index 0000000000..1d7f8d71a9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/GenericPersistenceUnitMetadata.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.EntityMappings; +import org.eclipse.jpt.core.context.orm.OrmPersistenceUnitDefaults; +import org.eclipse.jpt.core.context.orm.PersistenceUnitMetadata; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.resource.orm.OrmPackage; +import org.eclipse.jpt.core.resource.orm.XmlEntityMappings; +import org.eclipse.jpt.core.resource.orm.XmlPersistenceUnitMetadata; +import org.eclipse.jpt.core.resource.xml.EmfTools; +import org.eclipse.jpt.core.utility.TextRange; + +/** + * <code>orm.xml</code> file + * <br> + * <code>persistence-unit-metadata</code> element + */ +public class GenericPersistenceUnitMetadata + extends AbstractOrmXmlContextNode + implements PersistenceUnitMetadata +{ + protected boolean xmlMappingMetadataComplete; + + protected final OrmPersistenceUnitDefaults persistenceUnitDefaults; + + + public GenericPersistenceUnitMetadata(EntityMappings parent) { + super(parent); + this.xmlMappingMetadataComplete = this.getResourceXmlMappingMetadataComplete(); + this.persistenceUnitDefaults = this.getXmlContextNodeFactory().buildPersistenceUnitDefaults(this); + } + + @Override + public EntityMappings getParent() { + return (EntityMappings) super.getParent(); + } + + public XmlEntityMappings getXmlEntityMappings() { + return this.getParent().getXmlEntityMappings(); + } + + + // ********** persistence unit metadata ********** + + public XmlPersistenceUnitMetadata buildXmlPersistenceUnitMetadata() { + return EmfTools.create( + this.getResourceNodeFactory(), + OrmPackage.eINSTANCE.getXmlPersistenceUnitMetadata(), + XmlPersistenceUnitMetadata.class + ); + } + + public XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadata() { + return this.getXmlEntityMappings().getPersistenceUnitMetadata(); + } + + + // ********** XML mapping metadata complete ********** + + public boolean isXmlMappingMetadataComplete() { + return this.xmlMappingMetadataComplete; + } + + public void setXmlMappingMetadataComplete(boolean xmlMappingMetadataComplete) { + boolean old = this.xmlMappingMetadataComplete; + this.xmlMappingMetadataComplete = xmlMappingMetadataComplete; + if (old != xmlMappingMetadataComplete) { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + if (xmlMetadata != null) { + xmlMetadata.setXmlMappingMetadataComplete(xmlMappingMetadataComplete); + if (xmlMetadata.isUnset()) { + this.getXmlEntityMappings().setPersistenceUnitMetadata(null); + } + } + else if (xmlMappingMetadataComplete) { + xmlMetadata = this.buildXmlPersistenceUnitMetadata(); + this.getXmlEntityMappings().setPersistenceUnitMetadata(xmlMetadata); + xmlMetadata.setXmlMappingMetadataComplete(xmlMappingMetadataComplete); + } + this.firePropertyChanged(XML_MAPPING_METADATA_COMPLETE_PROPERTY, old, xmlMappingMetadataComplete); + } + } + + protected void setXmlMappingMetadataComplete_(boolean xmlMappingMetadataComplete) { + boolean old = this.xmlMappingMetadataComplete; + this.xmlMappingMetadataComplete = xmlMappingMetadataComplete; + this.firePropertyChanged(XML_MAPPING_METADATA_COMPLETE_PROPERTY, old, xmlMappingMetadataComplete); + } + + protected boolean getResourceXmlMappingMetadataComplete() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata != null) ? xmlMetadata.isXmlMappingMetadataComplete() : false; + } + + + // ********** persistence unit defaults ********** + + public OrmPersistenceUnitDefaults getPersistenceUnitDefaults() { + return this.persistenceUnitDefaults; + } + + + // ********** miscellaneous ********** + + public void update() { + this.setXmlMappingMetadataComplete_(this.getResourceXmlMappingMetadataComplete()); + this.persistenceUnitDefaults.update(); + } + + public TextRange getValidationTextRange() { + if (this.getXmlPersistenceUnitMetadata() != null) { + return this.getXmlPersistenceUnitMetadata().getValidationTextRange(); + } + return this.getXmlEntityMappings().getValidationTextRange(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/NullOrmJoinColumnJoiningStrategy.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/NullOrmJoinColumnJoiningStrategy.java new file mode 100644 index 0000000000..96833ee6cc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/NullOrmJoinColumnJoiningStrategy.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import java.util.ListIterator; +import org.eclipse.jpt.core.context.JoinColumn; +import org.eclipse.jpt.core.context.JoinColumnEnabledRelationshipReference; +import org.eclipse.jpt.core.context.JoinColumnJoiningStrategy; +import org.eclipse.jpt.core.context.RelationshipMapping; +import org.eclipse.jpt.core.context.TypeMapping; +import org.eclipse.jpt.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.core.context.orm.OrmJoinColumnJoiningStrategy; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.db.Table; + +public class NullOrmJoinColumnJoiningStrategy + extends AbstractOrmXmlContextNode + implements OrmJoinColumnJoiningStrategy +{ + + protected NullOrmJoinColumnJoiningStrategy(JoinColumnEnabledRelationshipReference parent) { + super(parent); + } + + public void initializeFrom(JoinColumnJoiningStrategy oldStrategy) { + throw new UnsupportedOperationException(); + } + + @Override + public JoinColumnEnabledRelationshipReference getParent() { + return (JoinColumnEnabledRelationshipReference) super.getParent(); + } + + public JoinColumnEnabledRelationshipReference getRelationshipReference() { + return this.getParent(); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getRelationshipReference().getRelationshipMapping(); + } + + public void addStrategy() { + throw new UnsupportedOperationException(); + } + + public void removeStrategy() { + //do nothing, no join column to remove + } + + public boolean isTargetForeignKeyRelationship() { + return false; + } + + public TypeMapping getRelationshipTarget() { + return null; + } + + // **************** join columns ******************************************* + + public ListIterator<OrmJoinColumn> joinColumns() { + throw new UnsupportedOperationException(); + } + + public int joinColumnsSize() { + throw new UnsupportedOperationException(); + } + + + // **************** default join column ************************************ + + public OrmJoinColumn getDefaultJoinColumn() { + throw new UnsupportedOperationException(); + } + + // **************** specified join columns ********************************* + + public ListIterator<OrmJoinColumn> specifiedJoinColumns() { + throw new UnsupportedOperationException(); + } + + public int specifiedJoinColumnsSize() { + throw new UnsupportedOperationException(); + } + + public boolean hasSpecifiedJoinColumns() { + return false; + } + + public OrmJoinColumn addSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + throw new UnsupportedOperationException(); + } + + // **************** resource => context ************************************ + + public void update() { + //no-op + } + + public TextRange getValidationTextRange() { + throw new UnsupportedOperationException(); + } + + public String getColumnTableNotValidDescription() { + throw new UnsupportedOperationException(); + } + + public Table getDbTable(String tableName) { + throw new UnsupportedOperationException(); + } + + public Table getReferencedColumnDbTable() { + throw new UnsupportedOperationException(); + } + + public String getTableName() { + return null; + } + + public boolean isOverridableAssociation() { + return false; + } + + public boolean tableNameIsInvalid(String tableName) { + throw new UnsupportedOperationException(); + } + + public TypeMapping getRelationshipSource() { + return getRelationshipMapping().getTypeMapping(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java new file mode 100644 index 0000000000..cdc8829c0a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.core.resource.orm.Attributes; +import org.eclipse.jpt.core.resource.orm.XmlNullAttributeMapping; + +/** + * This will be used in cases where the java support attribute mapping types + * that are not supported by the particular version of the orm.xml file. For example, + * EclipseLink supports variable 1-1 mappings, but the generic orm.xml file does not. + */ +public class UnsupportedOrmAttributeMapping + extends AbstractOrmAttributeMapping<XmlNullAttributeMapping> +{ + + public UnsupportedOrmAttributeMapping(OrmPersistentAttribute parent, XmlNullAttributeMapping resourceMapping) { + super(parent, resourceMapping); + } + + public int getXmlSequence() { + return -1; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmAttributeMapping(this); + } + + public String getKey() { + //this ends up returning the java attribute mapping key + return this.resourceAttributeMapping.getMappingKey(); + } + + public void addToResourceModel(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + public void removeFromResourceModel(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java new file mode 100644 index 0000000000..7b679a02d9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericClassRef.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.AccessType; +import org.eclipse.jpt.core.context.java.JavaPersistentType; +import org.eclipse.jpt.core.context.persistence.ClassRef; +import org.eclipse.jpt.core.context.persistence.MappingFileRef; +import org.eclipse.jpt.core.context.persistence.PersistenceStructureNodes; +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.core.resource.persistence.XmlJavaClassRef; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.StringTools; +import org.eclipse.jpt.utility.internal.Tools; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Context persistence.xml class reference + */ +public class GenericClassRef + extends AbstractPersistenceXmlContextNode + implements ClassRef +{ + // this is null for an "implied" class ref + protected final XmlJavaClassRef xmlJavaClassRef; + + protected String className; + + protected JavaPersistentType javaPersistentType; + + + // ********** construction/initialization ********** + + /** + * Construct an "specified" class ref; i.e. a class ref with + * an explicit entry in the persistence.xml. + */ + public GenericClassRef(PersistenceUnit parent, XmlJavaClassRef classRef) { + this(parent, classRef, classRef.getJavaClass()); + } + + /** + * Construct an "implied" class ref; i.e. a class ref without + * an explicit entry in the persistence.xml. + */ + public GenericClassRef(PersistenceUnit parent, String className) { + this(parent, null, className); + } + + protected GenericClassRef(PersistenceUnit parent, XmlJavaClassRef classRef, String className) { + super(parent); + this.xmlJavaClassRef = classRef; + this.initialize(className); + } + + protected void initialize(String typeName) { + this.className = typeName; + this.javaPersistentType = this.buildJavaPersistentType(); + } + + @Override + public PersistenceUnit getParent() { + return (PersistenceUnit) super.getParent(); + } + + public XmlJavaClassRef getResourceClassRef() { + return this.xmlJavaClassRef; + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return PersistenceStructureNodes.CLASS_REF_ID; + } + + public JpaStructureNode getStructureNode(int textOffset) { + return this; + } + + public TextRange getSelectionTextRange() { + return this.isVirtual() ? null : this.xmlJavaClassRef.getSelectionTextRange(); + } + + public void dispose() { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + } + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getOverridePersistentTypeAccess() { + // no access type at this level overrides any local access type specification + return null; + } + + public AccessType getDefaultPersistentTypeAccess() { + return this.getPersistenceUnit().getDefaultAccess(); + } + + + // ********** queries ********** + + public boolean isFor(String typeName) { + return Tools.valuesAreEqual(typeName, this.getJavaClassName()); + } + + public boolean isVirtual() { + return this.xmlJavaClassRef == null; + } + + public boolean containsOffset(int textOffset) { + return this.isNotVirtual() && this.xmlJavaClassRef.containsOffset(textOffset); + } + + protected boolean isNotVirtual() { + return ! this.isVirtual(); + } + + + // ********** class name ********** + + public String getClassName() { + return this.className; + } + + public void setClassName(String className) { + String old = this.className; + this.className = className; + this.xmlJavaClassRef.setJavaClass(className); + this.firePropertyChanged(CLASS_NAME_PROPERTY, old, className); + } + + protected void setClassName_(String newClassName) { + String old = this.className; + this.className = newClassName; + this.firePropertyChanged(CLASS_NAME_PROPERTY, old, newClassName); + } + + /** + * Nested classes will be qualified with a '$'; the Java name is qualified + * with a '.'. Like <code>className</code>, this can be <code>null</code>. + */ + protected String getJavaClassName() { + return StringTools.stringIsEmpty(this.className) ? null : this.className.replace('$', '.'); + } + + + // ********** java persistent type ********** + + public JavaPersistentType getJavaPersistentType() { + return this.javaPersistentType; + } + + protected void setJavaPersistentType(JavaPersistentType javaPersistentType) { + JavaPersistentType old = this.javaPersistentType; + this.javaPersistentType = javaPersistentType; + this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType); + } + + protected JavaPersistentType buildJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + return (jrpt == null) ? null : this.buildJavaPersistentType(jrpt); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + protected void updateJavaPersistentType() { + JavaResourcePersistentType jrpt = this.getJavaResourcePersistentType(); + if (jrpt == null) { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(null); + } + } else { + if (this.javaPersistentType == null) { + this.setJavaPersistentType(this.buildJavaPersistentType(jrpt)); + } else { + this.javaPersistentType.update(jrpt); + } + } + } + + protected JavaResourcePersistentType getJavaResourcePersistentType() { + String javaClassName = this.getJavaClassName(); + return (javaClassName == null) ? null : this.getJpaProject().getJavaResourcePersistentType(javaClassName); + } + + + // ********** updating ********** + + public void update() { + this.update(this.xmlJavaClassRef.getJavaClass()); + } + + public void update(String typeName) { + this.setClassName_(typeName); + this.updateJavaPersistentType(); + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.javaPersistentType != null) { + this.javaPersistentType.postUpdate(); + } + } + + // ********** XmlContextNode implementation ********** + + public TextRange getValidationTextRange() { + return this.isVirtual() ? null : this.xmlJavaClassRef.getValidationTextRange(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + if (StringTools.stringIsEmpty(this.className)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_UNSPECIFIED_CLASS, + this, + this.getValidationTextRange() + ) + ); + return; + } + + if (this.javaPersistentType == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_NONEXISTENT_CLASS, + new String[] {this.getJavaClassName()}, + this, + this.getValidationTextRange() + ) + ); + return; + } + + // 190062 validate Java class only if this is the only reference to it; + // i.e. the persistence.xml ref is the only ref - none of the mapping + // files reference the same class + boolean validateJavaPersistentType = true; + for (Iterator<MappingFileRef> stream = this.getPersistenceUnit().mappingFileRefsContaining(this.getJavaClassName()); stream.hasNext(); ) { + validateJavaPersistentType = false; + MappingFileRef mappingFileRef = stream.next(); + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.LOW_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_REDUNDANT_CLASS, + new String[] {this.getJavaClassName(), mappingFileRef.getFileName()}, + this, + this.getValidationTextRange() + ) + ); + } + + if (validateJavaPersistentType) { + this.validateJavaPersistentType(messages, reporter); + } + } + + protected void validateJavaPersistentType(List<IMessage> messages, IReporter reporter) { + try { + this.javaPersistentType.validate(messages, reporter); + } catch (Throwable t) { + JptCorePlugin.log(t); + } + } + + + // ********** misc ********** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.getJavaClassName()); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericJarFileRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericJarFileRef.java new file mode 100644 index 0000000000..80b33e73c8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericJarFileRef.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.persistence.AbstractJarFileRef; +import org.eclipse.jpt.core.resource.persistence.XmlJarFileRef; + +/** + * Context JAR file reference (from the persistence unit) + */ +public class GenericJarFileRef + extends AbstractJarFileRef +{ + public GenericJarFileRef(PersistenceUnit parent, XmlJarFileRef xmlJarFileRef) { + super(parent, xmlJarFileRef); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericMappingFileRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericMappingFileRef.java new file mode 100644 index 0000000000..1b09a7f729 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericMappingFileRef.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.persistence.AbstractMappingFileRef; +import org.eclipse.jpt.core.resource.persistence.XmlMappingFileRef; +import org.eclipse.jpt.core.utility.TextRange; + +/** + * <code>persistence.xml</code> file + * <br> + * <code>mapping-file</code> element + */ +public class GenericMappingFileRef + extends AbstractMappingFileRef +{ + protected XmlMappingFileRef xmlMappingFileRef; + + + // ********** construction/initialization ********** + + public GenericMappingFileRef(PersistenceUnit parent, XmlMappingFileRef xmlMappingFileRef) { + super(parent, xmlMappingFileRef.getFileName()); + this.xmlMappingFileRef = xmlMappingFileRef; + } + + + // ********** file name ********** + + public void setFileName(String fileName) { + String old = this.fileName; + this.fileName = fileName; + this.xmlMappingFileRef.setFileName(fileName); + this.firePropertyChanged(FILE_NAME_PROPERTY, old, fileName); + } + + protected void setFileName_(String newFileName) { + String old = this.fileName; + this.fileName = newFileName; + this.firePropertyChanged(FILE_NAME_PROPERTY, old, newFileName); + } + + + // ********** MappingFileRef implementation ********** + + public void update(XmlMappingFileRef mappingFileRef) { + this.xmlMappingFileRef = mappingFileRef; + this.setFileName_(mappingFileRef.getFileName()); + this.update(); + } + + public boolean isImplied() { + return false; + } + + public boolean containsOffset(int textOffset) { + return this.xmlMappingFileRef.containsOffset(textOffset); + } + + + // ********** JpaStructureNode implementation ********** + + public TextRange getSelectionTextRange() { + return this.xmlMappingFileRef.getSelectionTextRange(); + } + + + // ********** XmlContextNode implementation ********** + + public TextRange getValidationTextRange() { + return this.xmlMappingFileRef.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistence.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistence.java new file mode 100644 index 0000000000..38b80c76f7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistence.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.persistence.PersistenceStructureNodes; +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.context.persistence.PersistenceXml; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.persistence.Persistence2_0; +import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.core.resource.persistence.PersistenceFactory; +import org.eclipse.jpt.core.resource.persistence.XmlPersistence; +import org.eclipse.jpt.core.resource.persistence.XmlPersistenceUnit; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.jpt.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.utility.internal.iterables.SingleElementIterable; +import org.eclipse.jpt.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericPersistence + extends AbstractPersistenceXmlContextNode + implements Persistence2_0 +{ + protected XmlPersistence xmlPersistence; + + // The implementation here is a single persistence unit, although the API + // is for a list. We want to support multiple persistence units someday.... + protected PersistenceUnit persistenceUnit; + + public GenericPersistence(PersistenceXml parent, XmlPersistence xmlPersistence) { + super(parent); + this.xmlPersistence = xmlPersistence; + this.initializePersistenceUnits(); + } + + public String getId() { + return PersistenceStructureNodes.PERSISTENCE_ID; + } + + public XmlPersistence getXmlPersistence() { + return this.xmlPersistence; + } + + @Override + public PersistenceXml getParent() { + return (PersistenceXml) super.getParent(); + } + + // **************** persistence units ************************************** + + public ListIterator<PersistenceUnit> persistenceUnits() { + return (this.persistenceUnit == null) ? EmptyListIterator.<PersistenceUnit>instance() : this.persistenceUnits_(); + } + + protected ListIterator<PersistenceUnit> persistenceUnits_() { + return new SingleElementListIterator<PersistenceUnit>(this.persistenceUnit); + } + + protected Iterable<PersistenceUnit> getPersistenceUnits() { + return (this.persistenceUnit == null) ? EmptyIterable.<PersistenceUnit>instance() : this.getPersistenceUnits_(); + } + + protected Iterable<PersistenceUnit> getPersistenceUnits_() { + return new SingleElementIterable<PersistenceUnit>(this.persistenceUnit); + } + + public int persistenceUnitsSize() { + return (this.persistenceUnit == null) ? 0 : 1; + } + + public PersistenceUnit addPersistenceUnit() { + return addPersistenceUnit(persistenceUnitsSize()); + } + + public PersistenceUnit addPersistenceUnit(int index) { + if (index > 0 || this.persistenceUnit != null) { + throw new IllegalStateException("This implementation does not support multiple persistence units."); //$NON-NLS-1$ + } + XmlPersistenceUnit xmlPersistenceUnit = PersistenceFactory.eINSTANCE.createXmlPersistenceUnit(); + this.persistenceUnit = buildPersistenceUnit(xmlPersistenceUnit); + this.xmlPersistence.getPersistenceUnits().add(xmlPersistenceUnit); + fireItemAdded(PERSISTENCE_UNITS_LIST, index, this.persistenceUnit); + return this.persistenceUnit; + } + + public void removePersistenceUnit(PersistenceUnit pu) { + if (pu != this.persistenceUnit) { + throw new IllegalArgumentException("Invalid persistence unit: " + pu); //$NON-NLS-1$ + } + removePersistenceUnit(0); + } + + public void removePersistenceUnit(int index) { + if (index > 0 || this.persistenceUnit == null) { + throw new IndexOutOfBoundsException("index: " + index); //$NON-NLS-1$ + } + PersistenceUnit oldPersistenceUnit = this.persistenceUnit; + this.persistenceUnit.dispose(); + this.persistenceUnit = null; + this.xmlPersistence.getPersistenceUnits().remove(index); + fireItemRemoved(PERSISTENCE_UNITS_LIST, index, oldPersistenceUnit); + } + + protected void addPersistenceUnit_(PersistenceUnit newPersistenceUnit) { + this.persistenceUnit = newPersistenceUnit; + fireItemAdded(PERSISTENCE_UNITS_LIST, 0, this.persistenceUnit); + } + + protected void removePersistenceUnit_(PersistenceUnit oldPersistenceUnit) { + this.persistenceUnit.dispose(); + this.persistenceUnit = null; + fireItemRemoved(PERSISTENCE_UNITS_LIST, 0, oldPersistenceUnit); + } + + + // **************** metamodel ********************************** + + public void initializeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).disposeMetamodel(); + } + } + + + // **************** updating *********************************************** + + protected void initializePersistenceUnits() { + // only adding one here, until we support multiple persistence units + if (this.xmlPersistence.getPersistenceUnits().size() > 0) { + this.persistenceUnit = buildPersistenceUnit(this.xmlPersistence.getPersistenceUnits().get(0)); + } + } + + public void update(XmlPersistence persistence) { + this.xmlPersistence = persistence; + XmlPersistenceUnit xmlPersistenceUnit = null; + if (persistence.getPersistenceUnits().size() > 0) { + xmlPersistenceUnit = persistence.getPersistenceUnits().get(0); + } + + if (this.persistenceUnit != null) { + if (xmlPersistenceUnit != null) { + this.persistenceUnit.update(xmlPersistenceUnit); + } + else { + removePersistenceUnit_(this.persistenceUnit); + } + } + else { + if (xmlPersistenceUnit != null) { + addPersistenceUnit_(buildPersistenceUnit(xmlPersistenceUnit)); + } + } + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.persistenceUnit != null) { + this.persistenceUnit.postUpdate(); + } + } + + protected PersistenceUnit buildPersistenceUnit(XmlPersistenceUnit xmlPersistenceUnit) { + return this.getContextNodeFactory().buildPersistenceUnit(this, xmlPersistenceUnit); + } + + + // ************************************************************************* + + public JpaStructureNode getStructureNode(int textOffset) { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + if (pu.containsOffset(textOffset)) { + return pu.getStructureNode(textOffset); + } + } + return this; + } + + public boolean containsOffset(int textOffset) { + return (this.xmlPersistence == null) ? false : this.xmlPersistence.containsOffset(textOffset); + } + + public TextRange getSelectionTextRange() { + return this.xmlPersistence.getSelectionTextRange(); + } + + public TextRange getValidationTextRange() { + return this.xmlPersistence.getValidationTextRange(); + } + + public void dispose() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + pu.dispose(); + } + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + validateVersion(messages); + this.checkForMultiplePersistenceUnits(messages); + this.validatePersistenceUnit(messages, reporter); + } + + protected void validateVersion(List<IMessage> messages) { + if (! latestDocumentVersion().equals(this.xmlPersistence.getVersion())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.LOW_SEVERITY, + JpaValidationMessages.XML_VERSION_NOT_LATEST, + this, + this.xmlPersistence.getVersionTextRange())); + } + } + + protected String latestDocumentVersion() { + return getJpaPlatform().getMostRecentSupportedResourceType( + JptCorePlugin.PERSISTENCE_XML_CONTENT_TYPE).getVersion(); + } + + /** + * extraneous persistence units can be + * accessed through the XmlPersistence resource object + */ + protected void checkForMultiplePersistenceUnits(List<IMessage> messages) { + if (this.xmlPersistence.getPersistenceUnits().size() > 1) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENCE_MULTIPLE_PERSISTENCE_UNITS, + this, + this.getValidationTextRange() + ) + ); + } + } + + protected void validatePersistenceUnit(List<IMessage> messages, IReporter reporter) { + if (this.persistenceUnit == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_NO_PERSISTENCE_UNIT, + this, + this.getValidationTextRange() + ) + ); + return; + } + this.persistenceUnit.validate(messages, reporter); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java new file mode 100644 index 0000000000..f64d46c892 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.core.context.persistence.Persistence; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceUnit; +import org.eclipse.jpt.core.resource.persistence.XmlPersistenceUnit; + +/** + * generic persistence-unit + */ +public class GenericPersistenceUnit + extends AbstractPersistenceUnit +{ + public GenericPersistenceUnit(Persistence parent, XmlPersistenceUnit xmlPersistenceUnit) { + super(parent, xmlPersistenceUnit); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java new file mode 100644 index 0000000000..b5f4aa822c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.core.resource.persistence.XmlProperty; +import org.eclipse.jpt.core.utility.TextRange; + +/** + * Straightforward implementation of the persistence unit property. + * Notifies the persistence unit of any changes to the property. + */ +public class GenericPersistenceUnitProperty + extends AbstractPersistenceXmlContextNode + implements PersistenceUnit.Property +{ + protected final XmlProperty xmlProperty; + protected String name; + protected String value; + + + public GenericPersistenceUnitProperty(PersistenceUnit parent, XmlProperty xmlProperty) { + super(parent); + this.xmlProperty = xmlProperty; + this.name = xmlProperty.getName(); + this.value = xmlProperty.getValue(); + } + + @Override + public PersistenceUnit getParent() { + return (PersistenceUnit) super.getParent(); + } + + public XmlProperty getXmlProperty() { + return this.xmlProperty; + } + + // ********** name ********** + + public String getName() { + return this.name; + } + + public void setName(String name) { + String old = this.name; + this.name = name; + if (attributeValueHasChanged(old, name)) { + this.xmlProperty.setName(name); + this.firePropertyChanged(NAME_PROPERTY, old, name); + getParent().propertyNameChanged(old, this.name, this.value); + } + } + + + // ********** value ********** + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + String old = this.value; + this.value = value; + if (attributeValueHasChanged(old, value)) { + this.xmlProperty.setValue(value); + this.firePropertyChanged(VALUE_PROPERTY, old, value); + getParent().propertyValueChanged(this.name, value); + } + } + + + // ********** updating ********** + + public void update() { + this.setName(this.xmlProperty.getName()); + this.setValue(this.xmlProperty.getValue()); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.xmlProperty.getValidationTextRange(); + } + + + // ********** misc ********** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + sb.append(" = "); //$NON-NLS-1$ + sb.append(this.value); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXml.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXml.java new file mode 100644 index 0000000000..80d40f7bcc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXml.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import java.util.List; +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.core.JpaFile; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JpaStructureNode; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.JpaRootContextNode; +import org.eclipse.jpt.core.context.persistence.Persistence; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.core.jpa2.context.persistence.Persistence2_0; +import org.eclipse.jpt.core.jpa2.context.persistence.PersistenceXml2_0; +import org.eclipse.jpt.core.resource.persistence.XmlPersistence; +import org.eclipse.jpt.core.resource.xml.JpaXmlResource; +import org.eclipse.jpt.core.utility.TextRange; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * context model persistence.xml + */ +public class GenericPersistenceXml + extends AbstractPersistenceXmlContextNode + implements PersistenceXml2_0 +{ + /** + * If the XML resource's content type changes a new instance of this object will be built + */ + protected JpaXmlResource xmlResource; // never null + + /** + * The resouce type will only change if the XML file's version changes + * (since, if the content type changes, we get garbage-collected). + */ + protected JpaResourceType resourceType; + + protected Persistence persistence; + + + public GenericPersistenceXml(JpaRootContextNode parent, JpaXmlResource resource) { + super(parent); + if ( ! resource.getContentType().isKindOf(JptCorePlugin.PERSISTENCE_XML_CONTENT_TYPE)) { + throw new IllegalArgumentException("Resource " + resource + " must have persistence xml content type"); //$NON-NLS-1$ //$NON-NLS-2$ + } + this.xmlResource = resource; + if (resource.getRootObject() != null) { + this.persistence = this.buildPersistence((XmlPersistence) resource.getRootObject()); + this.resourceType = resource.getResourceType(); + } + } + + + // ********** XmlFile implementation ********** + + public JpaXmlResource getXmlResource() { + return this.xmlResource; + } + + + // ********** AbstractJpaNode overrides ********** + + @Override + public IResource getResource() { + return this.xmlResource.getFile(); + } + + + // ********** AbstractJpaContextNode overrides ********** + + @Override + public JpaResourceType getResourceType() { + return this.xmlResource.getResourceType(); + } + + + // ********** persistence ********** + + public Persistence getPersistence() { + return this.persistence; + } + + protected void setPersistence(Persistence persistence) { + Persistence old = this.persistence; + this.persistence = persistence; + this.firePropertyChanged(PERSISTENCE_PROPERTY, old, persistence); + } + + protected Persistence buildPersistence(XmlPersistence xmlPersistence) { + return this.getContextNodeFactory().buildPersistence(this, xmlPersistence); + } + + + // ********** metamodel ********** + + public void initializeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).disposeMetamodel(); + } + } + + + // ********** updating ********** + + public void update() { + XmlPersistence oldXmlPersistence = (this.persistence == null) ? null : this.persistence.getXmlPersistence(); + XmlPersistence newXmlPersistence = (XmlPersistence) this.xmlResource.getRootObject(); + JpaResourceType newResourceType = this.xmlResource.getResourceType(); + + // if the old and new xml persistences are different instances, + // we scrap the old and rebuild. this can happen when the resource + // model drastically changes, such as a cvs checkout or an edit reversion + if ((oldXmlPersistence != newXmlPersistence) + || (newXmlPersistence == null) + || this.valuesAreDifferent(this.resourceType, newResourceType)) { + + if (this.persistence != null) { + getJpaFile().removeRootStructureNode(this.xmlResource); + this.persistence.dispose(); + setPersistence(null); + } + } + + this.resourceType = newResourceType; + + if (newXmlPersistence != null) { + if (this.persistence != null) { + this.persistence.update(newXmlPersistence); + } + else { + setPersistence(buildPersistence(newXmlPersistence)); + } + + this.getJpaFile().addRootStructureNode(this.xmlResource, this.persistence); + } + } + + @Override + public void postUpdate() { + super.postUpdate(); + if (this.persistence != null) { + this.persistence.postUpdate(); + } + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + // isn't actually displayed, so needs no details page + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + if (this.persistence.containsOffset(textOffset)) { + return this.persistence.getStructureNode(textOffset); + } + return this; + } + + // never actually selected + public TextRange getSelectionTextRange() { + return TextRange.Empty.instance(); + } + + public void dispose() { + if (this.persistence != null) { + this.persistence.dispose(); + } + JpaFile jpaFile = getJpaFile(); + if (jpaFile != null) { + jpaFile.removeRootStructureNode(this.xmlResource); + } + } + + protected JpaFile getJpaFile() { + return this.getJpaFile(this.xmlResource.getFile()); + } + + + // ********** validation ********** + + // never actually selected + public TextRange getValidationTextRange() { + return TextRange.Empty.instance(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + if (this.persistence == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_XML_INVALID_CONTENT, + this + ) + ); + return; + } + + this.persistence.validate(messages, reporter); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java new file mode 100644 index 0000000000..1a79b2c05e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.jpt.core.JpaResourceType; +import org.eclipse.jpt.core.JptCorePlugin; +import org.eclipse.jpt.core.context.persistence.PersistenceXmlContextNodeFactory; +import org.eclipse.jpt.core.context.persistence.PersistenceXmlDefinition; +import org.eclipse.jpt.core.internal.context.persistence.AbstractPersistenceXmlDefinition; +import org.eclipse.jpt.core.internal.context.persistence.GenericPersistenceXmlContextNodeFactory; +import org.eclipse.jpt.core.resource.persistence.PersistenceFactory; + +public class GenericPersistenceXmlDefinition + extends AbstractPersistenceXmlDefinition +{ + // singleton + private static final PersistenceXmlDefinition INSTANCE = + new GenericPersistenceXmlDefinition(); + + + /** + * Return the singleton + */ + public static PersistenceXmlDefinition instance() { + return INSTANCE; + } + + + /** + * Enforce singleton usage + */ + private GenericPersistenceXmlDefinition() { + super(); + } + + + public EFactory getResourceNodeFactory() { + return PersistenceFactory.eINSTANCE; + } + + @Override + protected PersistenceXmlContextNodeFactory buildContextNodeFactory() { + return new GenericPersistenceXmlContextNodeFactory(); + } + + public JpaResourceType getResourceType() { + return JptCorePlugin.PERSISTENCE_XML_1_0_RESOURCE_TYPE; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java new file mode 100644 index 0000000000..b7c93efffa --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.core.internal.context.persistence.AbstractMappingFileRef; +import org.eclipse.jpt.core.resource.persistence.XmlMappingFileRef; +import org.eclipse.jpt.core.utility.TextRange; + +/** + * Used by the persistence unit for the + * <code>META-INF/orm.xml</code> file when it is not explicitly listed + * in the <code>persistence.xml</code> file. + */ +public class ImpliedMappingFileRef + extends AbstractMappingFileRef +{ + + // ********** construction/initialization ********** + + public ImpliedMappingFileRef(PersistenceUnit parent, String resourceFileName) { + super(parent, resourceFileName); + } + + + // ********** MappingFileRef implementation ********** + + public boolean isImplied() { + return true; + } + + public void setFileName(String fileName) { + throw new UnsupportedOperationException("Cannot set an implied mapping file ref's 'fileName': " + fileName); //$NON-NLS-1$ + } + + public boolean containsOffset(int textOffset) { + return false; + } + + public void update(XmlMappingFileRef mappingFileRef) { + if (mappingFileRef != null) { + throw new IllegalArgumentException("an implied mapping file ref's xml mapping file ref must be null: " + mappingFileRef); //$NON-NLS-1$ + } + this.update(); + } + + + // ********** JpaStructureNode implementation ********** + + public TextRange getSelectionTextRange() { + return null; + } + + + // ********** XmlContextNode implementation ********** + + public TextRange getValidationTextRange() { + return this.getPersistenceUnit().getValidationTextRange(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverride1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverride1_0Annotation.java new file mode 100644 index 0000000000..2837174908 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverride1_0Annotation.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.binary; + +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jpt.core.internal.resource.java.binary.BinaryAssociationOverrideAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; + +/** + * javax.persistence.AssociationOverride + */ +public final class BinaryAssociationOverride1_0Annotation + extends BinaryAssociationOverrideAnnotation +{ + + public BinaryAssociationOverride1_0Annotation(JavaResourceNode parent, IAnnotation jdtAnnotation) { + super(parent, jdtAnnotation); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverrides1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverrides1_0Annotation.java new file mode 100644 index 0000000000..6648edb213 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryAssociationOverrides1_0Annotation.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.binary; + +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jpt.core.internal.resource.java.binary.BinaryAssociationOverridesAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.resource.java.NestableAssociationOverrideAnnotation; + +/** + * javax.persistence.AssociationOverrides + */ +public final class BinaryAssociationOverrides1_0Annotation + extends BinaryAssociationOverridesAnnotation +{ + + public BinaryAssociationOverrides1_0Annotation(JavaResourceNode parent, IAnnotation jdtAnnotation) { + super(parent, jdtAnnotation); + } + + @Override + protected NestableAssociationOverrideAnnotation buildAssociationOverride(Object jdtAssociationOverride) { + return new BinaryAssociationOverride1_0Annotation(this, (IAnnotation) jdtAssociationOverride); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQueries1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQueries1_0Annotation.java new file mode 100644 index 0000000000..5d6435121f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQueries1_0Annotation.java @@ -0,0 +1,32 @@ +/******************************************************************************* +* Copyright (c) 2009 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0, which accompanies this distribution +* and is available at http://www.eclipse.org/legal/epl-v10.html. +* +* Contributors: +* Oracle - initial API and implementation +*******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.binary; + +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jpt.core.internal.resource.java.binary.BinaryNamedQueriesAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.resource.java.NamedQueryAnnotation; + +/** + * javax.persistence.NamedQueries + */ +public final class BinaryNamedQueries1_0Annotation + extends BinaryNamedQueriesAnnotation +{ + public BinaryNamedQueries1_0Annotation(JavaResourceNode parent, IAnnotation jdtAnnotation) { + super(parent, jdtAnnotation); + } + + @Override + protected NamedQueryAnnotation buildNamedQuery(Object jdtQuery) { + return new BinaryNamedQuery1_0Annotation(this, (IAnnotation) jdtQuery); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQuery1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQuery1_0Annotation.java new file mode 100644 index 0000000000..3ddb0353c1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinaryNamedQuery1_0Annotation.java @@ -0,0 +1,27 @@ +/******************************************************************************* +* Copyright (c) 2009 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0, which accompanies this distribution +* and is available at http://www.eclipse.org/legal/epl-v10.html. +* +* Contributors: +* Oracle - initial API and implementation +*******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.binary; + +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jpt.core.internal.resource.java.binary.BinaryNamedQueryAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; + +/** + * javax.persistence.NamedQuery + */ +public final class BinaryNamedQuery1_0Annotation + extends BinaryNamedQueryAnnotation +{ + + public BinaryNamedQuery1_0Annotation(JavaResourceNode parent, IAnnotation jdtAnnotation) { + super(parent, jdtAnnotation); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinarySequenceGenerator1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinarySequenceGenerator1_0Annotation.java new file mode 100644 index 0000000000..573dfee8ec --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/binary/BinarySequenceGenerator1_0Annotation.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.binary; + +import org.eclipse.jdt.core.IAnnotation; +import org.eclipse.jpt.core.internal.resource.java.binary.BinarySequenceGeneratorAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; + +/** + * javax.persistence.SequenceGenerator + */ +public final class BinarySequenceGenerator1_0Annotation + extends BinarySequenceGeneratorAnnotation +{ + + public BinarySequenceGenerator1_0Annotation(JavaResourceNode parent, IAnnotation jdtAnnotation) { + super(parent, jdtAnnotation); + } + +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverride1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverride1_0Annotation.java new file mode 100644 index 0000000000..617747551f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverride1_0Annotation.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.source; + +import org.eclipse.jpt.core.internal.resource.java.source.SourceAssociationOverrideAnnotation; +import org.eclipse.jpt.core.internal.utility.jdt.MemberAnnotationAdapter; +import org.eclipse.jpt.core.internal.utility.jdt.MemberIndexedAnnotationAdapter; +import org.eclipse.jpt.core.internal.utility.jdt.NestedIndexedDeclarationAnnotationAdapter; +import org.eclipse.jpt.core.resource.java.JPA; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.utility.jdt.AnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.DeclarationAnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.IndexedAnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.IndexedDeclarationAnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.Member; + +/** + * javax.persistence.AssociationOverride + */ +public final class SourceAssociationOverride1_0Annotation + extends SourceAssociationOverrideAnnotation +{ + + // ********** construction/initialization ********** + + public SourceAssociationOverride1_0Annotation(JavaResourceNode parent, Member member, DeclarationAnnotationAdapter daa, AnnotationAdapter annotationAdapter) { + super(parent, member, daa, annotationAdapter); + } + + // ********** static methods ********** + + public static SourceAssociationOverride1_0Annotation buildAssociationOverride(JavaResourceNode parent, Member member) { + return new SourceAssociationOverride1_0Annotation(parent, member, DECLARATION_ANNOTATION_ADAPTER, new MemberAnnotationAdapter(member, DECLARATION_ANNOTATION_ADAPTER)); + } + + static SourceAssociationOverride1_0Annotation buildNestedAssociationOverride(JavaResourceNode parent, Member member, int index, DeclarationAnnotationAdapter attributeOverridesAdapter) { + IndexedDeclarationAnnotationAdapter idaa = buildNestedDeclarationAnnotationAdapter(index, attributeOverridesAdapter); + IndexedAnnotationAdapter annotationAdapter = new MemberIndexedAnnotationAdapter(member, idaa); + return new SourceAssociationOverride1_0Annotation(parent, member, idaa, annotationAdapter); + } + + protected static IndexedDeclarationAnnotationAdapter buildNestedDeclarationAnnotationAdapter(int index, DeclarationAnnotationAdapter attributeOverridesAdapter) { + return new NestedIndexedDeclarationAnnotationAdapter(attributeOverridesAdapter, index, JPA.ASSOCIATION_OVERRIDE); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverrides1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverrides1_0Annotation.java new file mode 100644 index 0000000000..44bf07b668 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceAssociationOverrides1_0Annotation.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.source; + +import org.eclipse.jpt.core.internal.resource.java.source.SourceAssociationOverridesAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.resource.java.NestableAssociationOverrideAnnotation; +import org.eclipse.jpt.core.utility.jdt.Member; + +/** + * javax.persistence.AssociationOverrides + */ +public final class SourceAssociationOverrides1_0Annotation + extends SourceAssociationOverridesAnnotation +{ + + public SourceAssociationOverrides1_0Annotation(JavaResourceNode parent, Member member) { + super(parent, member); + } + + @Override + protected NestableAssociationOverrideAnnotation buildAssociationOverride(int index) { + return SourceAssociationOverride1_0Annotation.buildNestedAssociationOverride(this, this.member, index, this.daa); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceNamedQuery1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceNamedQuery1_0Annotation.java new file mode 100644 index 0000000000..6e1de34158 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceNamedQuery1_0Annotation.java @@ -0,0 +1,33 @@ +/******************************************************************************* +* Copyright (c) 2009, 2010 Oracle. All rights reserved. +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License v1.0, which accompanies this distribution +* and is available at http://www.eclipse.org/legal/epl-v10.html. +* +* Contributors: +* Oracle - initial API and implementation +*******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.source; + +import org.eclipse.jpt.core.internal.resource.java.source.SourceNamedQueryAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.utility.jdt.AnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.DeclarationAnnotationAdapter; +import org.eclipse.jpt.core.utility.jdt.Type; + +/** + * javax.persistence.NamedQuery + */ +public final class SourceNamedQuery1_0Annotation + extends SourceNamedQueryAnnotation +{ + + // ********** constructors ********** + public SourceNamedQuery1_0Annotation(JavaResourceNode parent, Type type) { + super(parent, type); + } + + public SourceNamedQuery1_0Annotation(JavaResourceNode parent, Type type, DeclarationAnnotationAdapter daa, AnnotationAdapter annotationAdapter) { + super(parent, type, daa, annotationAdapter); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceSequenceGenerator1_0Annotation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceSequenceGenerator1_0Annotation.java new file mode 100644 index 0000000000..27ac7f42a3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/resource/java/source/SourceSequenceGenerator1_0Annotation.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.core.internal.jpa1.resource.java.source; + +import org.eclipse.jpt.core.internal.resource.java.source.SourceSequenceGeneratorAnnotation; +import org.eclipse.jpt.core.resource.java.JavaResourceNode; +import org.eclipse.jpt.core.utility.jdt.Member; + +/** + * javax.persistence.SequenceGenerator + */ +public final class SourceSequenceGenerator1_0Annotation + extends SourceSequenceGeneratorAnnotation +{ + + public SourceSequenceGenerator1_0Annotation(JavaResourceNode parent, Member member) { + super(parent, member); + } + +} |