Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmoore2011-02-06 02:07:28 +0000
committerkmoore2011-02-06 02:07:28 +0000
commitc9c9e2b3e236ad701f642b72bca0cfabcac1d97b (patch)
tree346196323dc94395c2348339ac67e4f4cec6ebbf /jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java
parent8f2746f6b8c2ddc81d653d54d280043c41ed4734 (diff)
downloadwebtools.dali-c9c9e2b3e236ad701f642b72bca0cfabcac1d97b.tar.gz
webtools.dali-c9c9e2b3e236ad701f642b72bca0cfabcac1d97b.tar.xz
webtools.dali-c9c9e2b3e236ad701f642b72bca0cfabcac1d97b.zip
renamed org.eclipse.jpt.core to org.eclipse.jpt.jpa.core
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java')
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaAttributeMapping.java319
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseColumn.java361
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java319
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMapping.java383
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMappingDefinition.java67
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddable.java48
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddedMappingDefinition.java63
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEntity.java1816
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaGenerator.java225
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMapping.java476
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMappingDefinition.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinColumnRelationshipStrategy.java348
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinTableRelationshipStrategy.java196
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJpaContextNode.java72
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMapping.java51
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMappingDefinition.java61
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMapping.java50
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMappingDefinition.java61
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappedSuperclass.java112
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappingRelationship.java132
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMultiRelationshipMapping.java780
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaNamedColumn.java292
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMapping.java86
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMappingDefinition.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMapping.java86
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMappingDefinition.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOverride.java215
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java816
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java722
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaQuery.java231
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaReadOnlyUniqueConstraint.java53
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaRelationshipMapping.java347
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSequenceGenerator.java135
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSingleRelationshipMapping.java156
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTable.java584
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTypeMapping.java293
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMapping.java276
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMappingDefinition.java59
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualBaseColumn.java238
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualNamedColumn.java141
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualOverride.java63
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualReferenceTable.java200
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualTable.java315
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaIdClassReference.java239
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToManyRelationship.java198
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToOneRelationship.java194
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappedByRelationshipStrategy.java262
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappingJoinColumnRelationshipStrategy.java216
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToManyRelationship.java272
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToOneRelationship.java300
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOverrideJoinColumnRelationshipStrategy.java249
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.java385
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaVirtualJoinTable.java333
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBaseColumnTextRangeResolver.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBasicMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddableDefinition.java62
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedIdMappingDefinition.java73
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityDefinition.java116
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityTextRangeResolver.java44
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaIdMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaJoinColumnTextRangeResolver.java38
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToManyMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToOneMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassDefinition.java79
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassTextRangeResolver.java46
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNamedColumnTextRangeResolver.java37
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNullTypeMapping.java84
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToManyMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToOneMappingDefinition.java34
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOverrideTextRangeResolver.java37
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPersistentAttributeTextRangeResolver.java33
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPrimaryKeyJoinColumnTextRangeResolver.java35
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTableTextRangeResolver.java45
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTransientMappingDefinition.java65
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTypeMappingTextRangeResolver.java33
-rw-r--r--jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaVersionMappingDefinition.java34
77 files changed, 15224 insertions, 0 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaAttributeMapping.java
new file mode 100644
index 0000000000..1a92c17ab5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaAttributeMapping.java
@@ -0,0 +1,319 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.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.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.Transformer;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.SingleElementIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.Column;
+import org.eclipse.jpt.jpa.core.context.ColumnMapping;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.internal.jpa2.context.SimpleMetamodelField;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.jpa2.context.AttributeMapping2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentAttribute2_0;
+import org.eclipse.jpt.jpa.core.jpa2.resource.java.JPA2_0;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java attribute mapping
+ * <p>
+ * The mapping annotation is <code>null</code> for default mappings.
+ * It will be faulted into existence whenever {@link #getAnnotationForUpdate()}
+ * is called. It will <em>not</em> return to <code>null</code> automatically
+ * when all its state is defaulted; it must be explicitly cleared via
+ * {@link JavaPersistentAttribute#setMappingKey(String)}.
+ */
+public abstract class AbstractJavaAttributeMapping<A extends Annotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaAttributeMapping, AttributeMapping2_0
+{
+ protected boolean default_;
+
+
+ protected AbstractJavaAttributeMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.default_ = this.buildDefault();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.updateDefault();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.getPersistentAttribute().getName();
+ }
+
+
+ // ********** annotation **********
+
+ @SuppressWarnings("unchecked")
+ public A getMappingAnnotation() {
+ return (A) this.getAnnotation_();
+ }
+
+ protected Annotation getAnnotation_() {
+ return this.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName());
+ }
+
+ protected abstract String getAnnotationName();
+
+ /**
+ * This method should only be called on mappings that can occur by default
+ * (e.g. <code>Basic</code>, <code>Embedded</code>, <code>OneToOne</code>,
+ * and <code>OneToMany</code>).
+ */
+ public A getAnnotationForUpdate() {
+ A annotation = this.getMappingAnnotation();
+ if (annotation == null) {
+ this.getPersistentAttribute().setMappingKey(this.getKey());
+ annotation = this.getMappingAnnotation();
+ if (annotation == null) {
+ throw new IllegalStateException("missing annotation: " + this); //$NON-NLS-1$
+ }
+ }
+ return annotation;
+ }
+
+
+ // ********** default **********
+
+ public boolean isDefault() {
+ return this.default_;
+ }
+
+ protected void setDefault(boolean default_) {
+ boolean old = this.default_;
+ this.default_ = default_;
+ this.firePropertyChanged(DEFAULT_PROPERTY, old, default_);
+ }
+
+ public void updateDefault() {
+ this.setDefault(this.buildDefault());
+ }
+
+ protected boolean buildDefault() {
+ return this.getMappingAnnotation() == null;
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaPersistentAttribute getParent() {
+ return (JavaPersistentAttribute) super.getParent();
+ }
+
+ public JavaPersistentAttribute getPersistentAttribute() {
+ return this.getParent();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return this.getPersistentAttribute().getOwningTypeMapping();
+ }
+
+ public JavaResourcePersistentAttribute getResourcePersistentAttribute() {
+ return this.getPersistentAttribute().getResourcePersistentAttribute();
+ }
+
+ public String getPrimaryKeyColumnName() {
+ return null;
+ }
+
+ public boolean isOverridableAttributeMapping() {
+ return false;
+ }
+
+ public boolean isOverridableAssociationMapping() {
+ return false;
+ }
+
+ public boolean isRelationshipOwner() {
+ return false;
+ }
+
+ public boolean isOwnedBy(AttributeMapping mapping) {
+ return false;
+ }
+
+ public boolean validatesAgainstDatabase() {
+ return this.getTypeMapping().validatesAgainstDatabase();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return this.getTypeMapping().resolveDbTable(tableName);
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.getName());
+ }
+
+
+ // ********** embedded mappings **********
+
+ public Iterator<String> allMappingNames() {
+ return new SingleElementIterator<String>(this.getName());
+ }
+
+ public Iterator<String> allOverridableAttributeMappingNames() {
+ return this.isOverridableAttributeMapping() ?
+ new SingleElementIterator<String>(this.getName()) :
+ EmptyIterator.<String>instance();
+ }
+
+ public Iterator<String> allOverridableAssociationMappingNames() {
+ return this.isOverridableAssociationMapping() ?
+ new SingleElementIterator<String>(this.getName()) :
+ EmptyIterator.<String>instance();
+ }
+
+ public Column resolveOverriddenColumn(String attributeName) {
+ ColumnMapping mapping = this.resolveColumnMapping(attributeName);
+ return (mapping == null) ? null : mapping.getColumn();
+ }
+
+ protected ColumnMapping resolveColumnMapping(String name) {
+ AttributeMapping mapping = this.resolveAttributeMapping(name);
+ return ((mapping != null) && mapping.isOverridableAttributeMapping()) ? (ColumnMapping) mapping : null;
+ }
+
+ public Relationship resolveOverriddenRelationship(String attributeName) {
+ RelationshipMapping mapping = this.resolveRelationshipMapping(attributeName);
+ return (mapping == null) ? null : mapping.getRelationship();
+ }
+
+ protected RelationshipMapping resolveRelationshipMapping(String name) {
+ AttributeMapping mapping = this.resolveAttributeMapping(name);
+ return ((mapping != null) && mapping.isOverridableAssociationMapping()) ? (RelationshipMapping) mapping : null;
+ }
+
+ public AttributeMapping resolveAttributeMapping(String attributeName) {
+ return this.getName().equals(attributeName) ? this : null;
+ }
+
+ protected Transformer<String, String> buildQualifierTransformer() {
+ return new MappingTools.QualifierTransformer(this.getName());
+ }
+
+ protected String unqualify(String attributeName) {
+ return MappingTools.unqualify(this.getName(), attributeName);
+ }
+
+
+ // ********** metamodel **********
+
+ public MetamodelField getMetamodelField() {
+ return new SimpleMetamodelField(
+ this.getMetamodelFieldModifiers(),
+ this.getMetamodelFieldTypeName(),
+ this.getMetamodelFieldTypeArgumentNames(),
+ this.getMetamodelFieldName()
+ );
+ }
+
+ protected Iterable<String> getMetamodelFieldModifiers() {
+ return STANDARD_METAMODEL_FIELD_MODIFIERS;
+ }
+
+ /**
+ * most mappings are "singular"
+ */
+ protected String getMetamodelFieldTypeName() {
+ return JPA2_0.SINGULAR_ATTRIBUTE;
+ }
+
+ protected final Iterable<String> getMetamodelFieldTypeArgumentNames() {
+ ArrayList<String> typeArgumentNames = new ArrayList<String>(3);
+ typeArgumentNames.add(this.getTypeMapping().getPersistentType().getName());
+ this.addMetamodelFieldTypeArgumentNamesTo(typeArgumentNames);
+ return typeArgumentNames;
+ }
+
+ /**
+ * by default, we add only the mapping's attribute type name;
+ * but collection relationship mappings will also need to add the key type
+ * name if the "collection" is of type java.util.Map
+ */
+ protected void addMetamodelFieldTypeArgumentNamesTo(ArrayList<String> typeArgumentNames) {
+ typeArgumentNames.add(this.getMetamodelTypeName());
+ }
+
+ public String getMetamodelTypeName() {
+ return ((JavaPersistentAttribute2_0) this.getPersistentAttribute()).getMetamodelTypeName();
+ }
+
+ protected String getMetamodelFieldName() {
+ return this.getName();
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.validateMappingType(messages, astRoot);
+ }
+
+ protected void validateMappingType(List<IMessage> messages, CompilationUnit astRoot) {
+ if ( ! this.getTypeMapping().attributeMappingKeyAllowed(this.getKey())) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.PERSISTENT_ATTRIBUTE_INVALID_MAPPING,
+ new String[] {this.getName()},
+ this,
+ this.getValidationTextRange(astRoot)
+ )
+ );
+ }
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.getMappingAnnotationTextRange(astRoot);
+ return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
+ }
+
+ protected TextRange getMappingAnnotationTextRange(CompilationUnit astRoot) {
+ A annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseColumn.java
new file mode 100644
index 0000000000..5e2dd96aec
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseColumn.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaBaseColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.resource.java.BaseColumnAnnotation;
+
+/**
+ * Java column or join column
+ */
+public abstract class AbstractJavaBaseColumn<A extends BaseColumnAnnotation, O extends JavaBaseColumn.Owner>
+ extends AbstractJavaNamedColumn<A, O>
+ implements JavaBaseColumn
+{
+ protected String specifiedTable;
+ protected String defaultTable;
+
+ protected Boolean specifiedUnique;
+ protected boolean defaultUnique;
+
+ protected Boolean specifiedNullable;
+ protected boolean defaultNullable;
+
+ protected Boolean specifiedInsertable;
+ protected boolean defaultInsertable;
+
+ protected Boolean specifiedUpdatable;
+ protected boolean defaultUpdatable;
+
+
+ protected AbstractJavaBaseColumn(JavaJpaContextNode parent, O owner) {
+ this(parent, owner, null);
+ }
+
+ protected AbstractJavaBaseColumn(JavaJpaContextNode parent, O owner, A columnAnnotation) {
+ super(parent, owner, columnAnnotation);
+ this.specifiedTable = this.buildSpecifiedTable();
+ this.specifiedUnique = this.buildSpecifiedUnique();
+ this.specifiedNullable = this.buildSpecifiedNullable();
+ this.specifiedInsertable = this.buildSpecifiedInsertable();
+ this.specifiedUpdatable = this.buildSpecifiedUpdatable();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedTable_(this.buildSpecifiedTable());
+ this.setSpecifiedUnique_(this.buildSpecifiedUnique());
+ this.setSpecifiedNullable_(this.buildSpecifiedNullable());
+ this.setSpecifiedInsertable_(this.buildSpecifiedInsertable());
+ this.setSpecifiedUpdatable_(this.buildSpecifiedUpdatable());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultTable(this.buildDefaultTable());
+ this.setDefaultUnique(this.buildDefaultUnique());
+ this.setDefaultNullable(this.buildDefaultNullable());
+ this.setDefaultInsertable(this.buildDefaultInsertable());
+ this.setDefaultUpdatable(this.buildDefaultUpdatable());
+ }
+
+
+ // ********** table **********
+
+ @Override
+ public String getTable() {
+ return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable;
+ }
+
+ public String getSpecifiedTable() {
+ return this.specifiedTable;
+ }
+
+ public void setSpecifiedTable(String table) {
+ if (this.valuesAreDifferent(this.specifiedTable, table)) {
+ this.getColumnAnnotation().setTable(table);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedTable_(table);
+ }
+ }
+
+ protected void setSpecifiedTable_(String table) {
+ String old = this.specifiedTable;
+ this.specifiedTable = table;
+ this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table);
+ }
+
+ protected String buildSpecifiedTable() {
+ return this.getColumnAnnotation().getTable();
+ }
+
+ 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);
+ }
+
+ protected String buildDefaultTable() {
+ return this.owner.getDefaultTableName();
+ }
+
+ public TextRange getTableTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.getColumnAnnotation().getTableTextRange(astRoot);
+ return (textRange != null) ? textRange : this.owner.getValidationTextRange(astRoot);
+ }
+
+
+ // ********** unique **********
+
+ public boolean isUnique() {
+ return (this.specifiedUnique != null) ? this.specifiedUnique.booleanValue() : this.isDefaultUnique();
+ }
+
+ public Boolean getSpecifiedUnique() {
+ return this.specifiedUnique;
+ }
+
+ public void setSpecifiedUnique(Boolean unique) {
+ if (this.valuesAreDifferent(this.specifiedUnique, unique)) {
+ this.getColumnAnnotation().setUnique(unique);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedUnique_(unique);
+ }
+ }
+
+ protected void setSpecifiedUnique_(Boolean unique) {
+ Boolean old = this.specifiedUnique;
+ this.specifiedUnique = unique;
+ this.firePropertyChanged(SPECIFIED_UNIQUE_PROPERTY, old, unique);
+ }
+
+ protected Boolean buildSpecifiedUnique() {
+ return this.getColumnAnnotation().getUnique();
+ }
+
+ public boolean isDefaultUnique() {
+ return this.defaultUnique;
+ }
+
+ protected void setDefaultUnique(boolean unique) {
+ boolean old = this.defaultUnique;
+ this.defaultUnique = unique;
+ this.firePropertyChanged(DEFAULT_UNIQUE_PROPERTY, old, unique);
+ }
+
+ protected boolean buildDefaultUnique() {
+ return DEFAULT_UNIQUE;
+ }
+
+
+ // ********** nullable **********
+
+ public boolean isNullable() {
+ return (this.specifiedNullable != null) ? this.specifiedNullable.booleanValue() : this.isDefaultNullable();
+ }
+
+ public Boolean getSpecifiedNullable() {
+ return this.specifiedNullable;
+ }
+
+ public void setSpecifiedNullable(Boolean nullable) {
+ if (this.valuesAreDifferent(this.specifiedNullable, nullable)) {
+ this.getColumnAnnotation().setNullable(nullable);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedNullable_(nullable);
+ }
+ }
+
+ protected void setSpecifiedNullable_(Boolean nullable) {
+ Boolean old = this.specifiedNullable;
+ this.specifiedNullable = nullable;
+ this.firePropertyChanged(SPECIFIED_NULLABLE_PROPERTY, old, nullable);
+ }
+
+ protected Boolean buildSpecifiedNullable() {
+ return this.getColumnAnnotation().getNullable();
+ }
+
+ public boolean isDefaultNullable() {
+ return this.defaultNullable;
+ }
+
+ protected void setDefaultNullable(boolean nullable) {
+ boolean old = this.defaultNullable;
+ this.defaultNullable = nullable;
+ this.firePropertyChanged(DEFAULT_NULLABLE_PROPERTY, old, nullable);
+ }
+
+ protected boolean buildDefaultNullable() {
+ return DEFAULT_NULLABLE;
+ }
+
+
+ // ********** insertable **********
+
+ public boolean isInsertable() {
+ return (this.specifiedInsertable != null) ? this.specifiedInsertable.booleanValue() : this.isDefaultInsertable();
+ }
+
+ public Boolean getSpecifiedInsertable() {
+ return this.specifiedInsertable;
+ }
+
+ public void setSpecifiedInsertable(Boolean insertable) {
+ if (this.valuesAreDifferent(this.specifiedInsertable, insertable)) {
+ this.getColumnAnnotation().setInsertable(insertable);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedInsertable_(insertable);
+ }
+ }
+
+ protected void setSpecifiedInsertable_(Boolean insertable) {
+ Boolean old = this.specifiedInsertable;
+ this.specifiedInsertable = insertable;
+ this.firePropertyChanged(SPECIFIED_INSERTABLE_PROPERTY, old, insertable);
+ }
+
+ protected Boolean buildSpecifiedInsertable() {
+ return this.getColumnAnnotation().getInsertable();
+ }
+
+ public boolean isDefaultInsertable() {
+ return this.defaultInsertable;
+ }
+
+ protected void setDefaultInsertable(boolean insertable) {
+ boolean old = this.defaultInsertable;
+ this.defaultInsertable = insertable;
+ this.firePropertyChanged(DEFAULT_INSERTABLE_PROPERTY, old, insertable);
+ }
+
+ protected boolean buildDefaultInsertable() {
+ return DEFAULT_INSERTABLE;
+ }
+
+
+ // ********** updatable **********
+
+ public boolean isUpdatable() {
+ return (this.specifiedUpdatable != null) ? this.specifiedUpdatable.booleanValue() : this.isDefaultUpdatable();
+ }
+
+ public Boolean getSpecifiedUpdatable() {
+ return this.specifiedUpdatable;
+ }
+
+ public void setSpecifiedUpdatable(Boolean updatable) {
+ if (this.valuesAreDifferent(this.specifiedUpdatable, updatable)) {
+ this.getColumnAnnotation().setUpdatable(updatable);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedUpdatable_(updatable);
+ }
+ }
+
+ protected void setSpecifiedUpdatable_(Boolean updatable) {
+ Boolean old = this.specifiedUpdatable;
+ this.specifiedUpdatable = updatable;
+ this.firePropertyChanged(SPECIFIED_UPDATABLE_PROPERTY, old, updatable);
+ }
+
+ protected Boolean buildSpecifiedUpdatable() {
+ return this.getColumnAnnotation().getUpdatable();
+ }
+
+ public boolean isDefaultUpdatable() {
+ return this.defaultUpdatable;
+ }
+
+ protected void setDefaultUpdatable(boolean updatable) {
+ boolean old = this.defaultUpdatable;
+ this.defaultUpdatable = updatable;
+ this.firePropertyChanged(DEFAULT_UPDATABLE_PROPERTY, old, updatable);
+ }
+
+ protected boolean buildDefaultUpdatable() {
+ return DEFAULT_UPDATABLE;
+ }
+
+
+ // ********** misc **********
+
+ protected void initializeFrom(ReadOnlyBaseColumn oldColumn) {
+ super.initializeFrom(oldColumn);
+ this.setSpecifiedTable(oldColumn.getSpecifiedTable());
+ this.setSpecifiedUnique(oldColumn.getSpecifiedUnique());
+ this.setSpecifiedNullable(oldColumn.getSpecifiedNullable());
+ this.setSpecifiedInsertable(oldColumn.getSpecifiedInsertable());
+ this.setSpecifiedUpdatable(oldColumn.getSpecifiedUpdatable());
+ }
+
+ protected void initializeFromVirtual(ReadOnlyBaseColumn virtualColumn) {
+ super.initializeFromVirtual(virtualColumn);
+ this.setSpecifiedTable(virtualColumn.getTable());
+ // ignore other settings?
+ }
+
+ public boolean tableNameIsInvalid() {
+ return this.owner.tableNameIsInvalid(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;
+ }
+ if (this.tableTouches(pos, astRoot)) {
+ return this.javaCandidateTableNames(filter);
+ }
+ return null;
+ }
+
+ protected boolean tableTouches(int pos, CompilationUnit astRoot) {
+ return this.getColumnAnnotation().tableTouches(pos, astRoot);
+ }
+
+ protected Iterator<String> javaCandidateTableNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.candidateTableNames(filter));
+ }
+
+ protected Iterator<String> candidateTableNames(Filter<String> filter) {
+ return new FilteringIterator<String>(this.candidateTableNames(), filter);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return this.owner.candidateTableNames();
+ }
+
+ @Override
+ protected NamedColumnTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaBaseColumnTextRangeResolver(this, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java
new file mode 100644
index 0000000000..ea3c1a97e2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBaseEmbeddedMapping.java
@@ -0,0 +1,319 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.Transformer;
+import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.AttributeOverride;
+import org.eclipse.jpt.jpa.core.context.AttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Column;
+import org.eclipse.jpt.jpa.core.context.Embeddable;
+import org.eclipse.jpt.jpa.core.context.OverrideContainer;
+import org.eclipse.jpt.jpa.core.context.Override_;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaBaseEmbeddedMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.context.AttributeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AttributeOverrideColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AttributeOverrideValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EmbeddableOverrideDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.orm.GenericOrmEmbeddedIdMapping;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * <code>orm.xml</code> embedded or embedded ID mapping
+ */
+public abstract class AbstractJavaBaseEmbeddedMapping<A extends Annotation>
+ extends AbstractJavaAttributeMapping<A>
+ implements JavaBaseEmbeddedMapping
+{
+ protected final JavaAttributeOverrideContainer attributeOverrideContainer;
+
+ protected Embeddable targetEmbeddable;
+
+
+ protected AbstractJavaBaseEmbeddedMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.attributeOverrideContainer = this.buildAttributeOverrideContainer();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.attributeOverrideContainer.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.attributeOverrideContainer.update();
+ this.setTargetEmbeddable(this.buildTargetEmbeddable());
+ }
+
+
+ // ********** attribute override container **********
+
+ public JavaAttributeOverrideContainer getAttributeOverrideContainer() {
+ return this.attributeOverrideContainer;
+ }
+
+ protected JavaAttributeOverrideContainer buildAttributeOverrideContainer() {
+ return this.getJpaFactory().buildJavaAttributeOverrideContainer(this, this.buildAttributeOverrideContainerOwner());
+ }
+
+ protected JavaAttributeOverrideContainer.Owner buildAttributeOverrideContainerOwner() {
+ return new AttributeOverrideContainerOwner();
+ }
+
+
+ // ********** target embeddable **********
+
+ public Embeddable getTargetEmbeddable() {
+ return this.targetEmbeddable;
+ }
+
+ protected void setTargetEmbeddable(Embeddable embeddable) {
+ Embeddable old = this.targetEmbeddable;
+ this.targetEmbeddable = embeddable;
+ this.firePropertyChanged(TARGET_EMBEDDABLE_PROPERTY, old, embeddable);
+ }
+
+ protected Embeddable buildTargetEmbeddable() {
+ return this.getPersistentAttribute().getEmbeddable();
+ }
+
+
+ // ********** embedded mappings **********
+
+ @Override
+ public Iterator<String> allOverridableAttributeMappingNames() {
+ return this.isJpa2_0Compatible() ?
+ this.embeddableOverridableAttributeMappingNames() :
+ super.allOverridableAttributeMappingNames();
+ }
+
+ protected Iterator<String> embeddableOverridableAttributeMappingNames() {
+ return this.qualifiedEmbeddableOverridableMappingNames(AttributeMappingTools.ALL_OVERRIDABLE_ATTRIBUTE_MAPPING_NAMES_TRANSFORMER);
+ }
+
+ @Override
+ public Iterator<String> allOverridableAssociationMappingNames() {
+ return this.isJpa2_0Compatible() ?
+ this.embeddableOverridableAssociationMappingNames() :
+ super.allOverridableAssociationMappingNames();
+ }
+
+ protected Iterator<String> embeddableOverridableAssociationMappingNames() {
+ return this.qualifiedEmbeddableOverridableMappingNames(AttributeMappingTools.ALL_OVERRIDABLE_ASSOCIATION_MAPPING_NAMES_TRANSFORMER);
+ }
+
+ protected Iterator<String> qualifiedEmbeddableOverridableMappingNames(Transformer<AttributeMapping, Iterator<String>> transformer) {
+ return new TransformationIterator<String, String>(this.embeddableAttributeMappingNames(transformer), this.buildQualifierTransformer());
+ }
+
+ protected Iterator<String> embeddableAttributeMappingNames(Transformer<AttributeMapping, Iterator<String>> transformer) {
+ return new CompositeIterator<String>(this.embeddableAttributeMappingNamesLists(transformer));
+ }
+
+ /**
+ * Return a list of lists; each nested list holds the names for one of the
+ * embedded mapping's target embeddable type mapping's attribute mappings
+ * (attribute or association mappings, depending on the specified transformer).
+ */
+ protected Iterator<Iterator<String>> embeddableAttributeMappingNamesLists(Transformer<AttributeMapping, Iterator<String>> transformer) {
+ return new TransformationIterator<AttributeMapping, Iterator<String>>(this.embeddableAttributeMappings(), transformer);
+ }
+
+ /**
+ * Return the target embeddable's attribute mappings.
+ */
+ protected Iterator<AttributeMapping> embeddableAttributeMappings() {
+ return ((this.targetEmbeddable != null) && (this.targetEmbeddable != this.getTypeMapping())) ?
+ this.targetEmbeddable.attributeMappings() :
+ EmptyIterator.<AttributeMapping>instance();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public Column resolveOverriddenColumn(String attributeName) {
+ return this.isJpa2_0Compatible() ? this.resolveOverriddenColumn_(attributeName) : null;
+ }
+
+ protected Column resolveOverriddenColumn_(String attributeName) {
+ attributeName = this.unqualify(attributeName);
+ if (attributeName == null) {
+ return null;
+ }
+ AttributeOverride override = this.attributeOverrideContainer.getSpecifiedOverrideNamed(attributeName);
+ // recurse into the target embeddable if necessary
+ return (override != null) ? override.getColumn() : this.resolveOverriddenColumnInTargetEmbeddable(attributeName);
+ }
+
+ protected Column resolveOverriddenColumnInTargetEmbeddable(String attributeName) {
+ return (this.targetEmbeddable == null) ? null : this.targetEmbeddable.resolveOverriddenColumn(attributeName);
+ }
+
+
+ // ********** 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.attributeOverrideContainer.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);
+
+ if (this.validateTargetEmbeddable(messages, astRoot)) {
+ this.validateOverrides(messages, reporter, astRoot);
+ }
+ }
+
+ protected boolean validateTargetEmbeddable(List<IMessage> messages, CompilationUnit astRoot) {
+ if (this.targetEmbeddable != null) {
+ return true;
+ }
+ String targetEmbeddableTypeName = this.getPersistentAttribute().getTypeName();
+ // if the type isn't resolvable, there will already be a java compile error
+ if (targetEmbeddableTypeName != null) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.TARGET_NOT_AN_EMBEDDABLE,
+ new String[] {targetEmbeddableTypeName},
+ this,
+ this.getValidationTextRange(astRoot)
+ )
+ );
+ }
+ return false;
+ }
+
+ protected void validateOverrides(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.attributeOverrideContainer.validate(messages, reporter, astRoot);
+ }
+
+
+ // ********** attribute override container owner *********
+
+ protected class AttributeOverrideContainerOwner
+ implements JavaAttributeOverrideContainer.Owner
+ {
+ public JavaResourcePersistentMember getResourcePersistentMember() {
+ return AbstractJavaBaseEmbeddedMapping.this.getResourcePersistentAttribute();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return AbstractJavaBaseEmbeddedMapping.this.getTypeMapping();
+ }
+
+ public TypeMapping getOverridableTypeMapping() {
+ return AbstractJavaBaseEmbeddedMapping.this.getTargetEmbeddable();
+ }
+
+ public Iterator<String> allOverridableNames() {
+ TypeMapping typeMapping = this.getOverridableTypeMapping();
+ return (typeMapping != null) ? this.allOverridableAttributeNames_(typeMapping) : EmptyIterator.<String>instance();
+ }
+
+ /**
+ * pre-condition: type mapping is not <code>null</code>
+ * <p>
+ * NB: Overridden in {@link GenericOrmEmbeddedIdMapping.AttributeOverrideContainerOwner}
+ */
+ protected Iterator<String> allOverridableAttributeNames_(TypeMapping typeMapping) {
+ return typeMapping.allOverridableAttributeNames();
+ }
+
+ public Column resolveOverriddenColumn(String attributeName) {
+ return MappingTools.resolveOverriddenColumn(this.getOverridableTypeMapping(), attributeName);
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return this.getTypeMapping().allAssociatedTableNames();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return this.getTypeMapping().resolveDbTable(tableName);
+ }
+
+ public String getDefaultTableName() {
+ return this.getTypeMapping().getPrimaryTableName();
+ }
+
+ public String getPossiblePrefix() {
+ return null;
+ }
+
+ public String getWritePrefix() {
+ return null;
+ }
+
+ // no maps, so all overrides are relevant
+ public boolean isRelevant(String overrideName) {
+ return true;
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return AbstractJavaBaseEmbeddedMapping.this.getValidationTextRange(astRoot);
+ }
+
+ public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) {
+ return new AttributeOverrideValidator((AttributeOverride) override, (AttributeOverrideContainer) container, textRangeResolver, new EmbeddableOverrideDescriptionProvider());
+ }
+
+ public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner owner, BaseColumnTextRangeResolver textRangeResolver) {
+ return new AttributeOverrideColumnValidator((AttributeOverride) override, column, textRangeResolver, new EntityTableDescriptionProvider());
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMapping.java
new file mode 100644
index 0000000000..1fa555f9cb
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMapping.java
@@ -0,0 +1,383 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.Association;
+import org.eclipse.jpt.common.utility.internal.SimpleAssociation;
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Converter;
+import org.eclipse.jpt.jpa.core.context.FetchType;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaBasicMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaEnumeratedConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaLobConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaTemporalConverter;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.NamedColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaConverter;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.BasicAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java basic mapping
+ */
+public abstract class AbstractJavaBasicMapping
+ extends AbstractJavaAttributeMapping<BasicAnnotation>
+ implements JavaBasicMapping
+{
+ protected final JavaColumn column;
+
+ protected FetchType specifiedFetch;
+ protected FetchType defaultFetch;
+
+ protected Boolean specifiedOptional;
+ protected boolean defaultOptional;
+
+ protected JavaConverter converter; // never null
+
+
+ protected static final JavaConverter.Adapter[] CONVERTER_ADAPTER_ARRAY = new JavaConverter.Adapter[] {
+ JavaEnumeratedConverter.Adapter.instance(),
+ JavaTemporalConverter.Adapter.instance(),
+ JavaLobConverter.Adapter.instance()
+ };
+ protected static final Iterable<JavaConverter.Adapter> CONVERTER_ADAPTERS = new ArrayIterable<JavaConverter.Adapter>(CONVERTER_ADAPTER_ARRAY);
+
+
+ protected AbstractJavaBasicMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.column = this.buildColumn();
+ this.specifiedFetch = this.buildSpecifiedFetch();
+ this.specifiedOptional = this.buildSpecifiedOptional();
+ this.converter = this.buildConverter();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.column.synchronizeWithResourceModel();
+ this.setSpecifiedFetch_(this.buildSpecifiedFetch());
+ this.setSpecifiedOptional_(this.buildSpecifiedOptional());
+ this.syncConverter();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.column.update();
+ this.setDefaultFetch(this.buildDefaultFetch());
+ this.setDefaultOptional(this.buildDefaultOptional());
+ this.converter.update();
+ }
+
+
+ // ********** column **********
+
+ public JavaColumn getColumn() {
+ return this.column;
+ }
+
+ protected JavaColumn buildColumn() {
+ return this.getJpaFactory().buildJavaColumn(this, this);
+ }
+
+
+ // ********** fetch **********
+
+ public FetchType getFetch() {
+ return (this.specifiedFetch != null) ? this.specifiedFetch : this.defaultFetch;
+ }
+
+ public FetchType getSpecifiedFetch() {
+ return this.specifiedFetch;
+ }
+
+ public void setSpecifiedFetch(FetchType fetch) {
+ if (this.valuesAreDifferent(fetch, this.specifiedFetch)) {
+ this.getAnnotationForUpdate().setFetch(FetchType.toJavaResourceModel(fetch));
+ this.setSpecifiedFetch_(fetch);
+ }
+ }
+
+ protected void setSpecifiedFetch_(FetchType fetch) {
+ FetchType old = this.specifiedFetch;
+ this.specifiedFetch = fetch;
+ this.firePropertyChanged(SPECIFIED_FETCH_PROPERTY, old, fetch);
+ }
+
+ protected FetchType buildSpecifiedFetch() {
+ BasicAnnotation annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : FetchType.fromJavaResourceModel(annotation.getFetch());
+ }
+
+ public FetchType getDefaultFetch() {
+ return this.defaultFetch;
+ }
+
+ protected void setDefaultFetch(FetchType fetch) {
+ FetchType old = this.defaultFetch;
+ this.defaultFetch = fetch;
+ this.firePropertyChanged(DEFAULT_FETCH_PROPERTY, old, fetch);
+ }
+
+ protected FetchType buildDefaultFetch() {
+ return DEFAULT_FETCH_TYPE;
+ }
+
+
+ // ********** optional **********
+
+ public boolean isOptional() {
+ return (this.specifiedOptional != null) ? this.specifiedOptional.booleanValue() : this.isDefaultOptional();
+ }
+
+ public Boolean getSpecifiedOptional() {
+ return this.specifiedOptional;
+ }
+
+ public void setSpecifiedOptional(Boolean optional) {
+ if (this.valuesAreDifferent(optional, this.specifiedOptional)) {
+ this.getAnnotationForUpdate().setOptional(optional);
+ this.setSpecifiedOptional_(optional);
+ }
+ }
+
+ protected void setSpecifiedOptional_(Boolean optional) {
+ Boolean old = this.specifiedOptional;
+ this.specifiedOptional = optional;
+ this.firePropertyChanged(SPECIFIED_OPTIONAL_PROPERTY, old, optional);
+ }
+
+ protected Boolean buildSpecifiedOptional() {
+ BasicAnnotation annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getOptional();
+ }
+
+ public boolean isDefaultOptional() {
+ return defaultOptional;
+ }
+
+ protected void setDefaultOptional(boolean optional) {
+ boolean old = this.defaultOptional;
+ this.defaultOptional = optional;
+ this.firePropertyChanged(DEFAULT_OPTIONAL_PROPERTY, old, optional);
+ }
+
+ protected boolean buildDefaultOptional() {
+ return DEFAULT_OPTIONAL;
+ }
+
+
+ // ********** converter **********
+
+ public JavaConverter getConverter() {
+ return this.converter;
+ }
+
+ public void setConverter(Class<? extends Converter> converterType) {
+ if (this.converter.getType() != converterType) {
+ this.converter.dispose();
+ JavaConverter.Adapter converterAdapter = this.getConverterAdapter(converterType);
+ this.retainConverterAnnotation(converterAdapter);
+ this.setConverter_(this.buildConverter(converterAdapter));
+ }
+ }
+
+ protected JavaConverter buildConverter(JavaConverter.Adapter converterAdapter) {
+ return (converterAdapter != null) ?
+ converterAdapter.buildNewConverter(this, this.getJpaFactory()) :
+ this.buildNullConverter();
+ }
+
+ protected void setConverter_(JavaConverter converter) {
+ Converter old = this.converter;
+ this.converter = converter;
+ this.firePropertyChanged(CONVERTER_PROPERTY, old, converter);
+ }
+
+ /**
+ * Clear all the converter annotations <em>except</em> for the annotation
+ * corresponding to the specified adapter. If the specified adapter is
+ * <code>null</code>, remove <em>all</em> the converter annotations.
+ */
+ protected void retainConverterAnnotation(JavaConverter.Adapter converterAdapter) {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter != converterAdapter) {
+ adapter.removeConverterAnnotation(resourceAttribute);
+ }
+ }
+ }
+
+ protected JavaConverter buildConverter() {
+ JpaFactory jpaFactory = this.getJpaFactory();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ JavaConverter javaConverter = adapter.buildConverter(this, jpaFactory);
+ if (javaConverter != null) {
+ return javaConverter;
+ }
+ }
+ return this.buildNullConverter();
+ }
+
+ protected void syncConverter() {
+ Association<JavaConverter.Adapter, Annotation> assoc = this.getConverterAnnotation();
+ if (assoc == null) {
+ if (this.converter.getType() != null) {
+ this.setConverter_(this.buildNullConverter());
+ }
+ } else {
+ JavaConverter.Adapter adapter = assoc.getKey();
+ Annotation annotation = assoc.getValue();
+ if ((this.converter.getType() == adapter.getConverterType()) &&
+ (this.converter.getConverterAnnotation() == annotation)) {
+ this.converter.synchronizeWithResourceModel();
+ } else {
+ this.setConverter_(adapter.buildConverter(annotation, this, this.getJpaFactory()));
+ }
+ }
+ }
+
+ /**
+ * Return the first converter annotation we find along with its corresponding
+ * adapter. Return <code>null</code> if there are no converter annotations.
+ */
+ protected Association<JavaConverter.Adapter, Annotation> getConverterAnnotation() {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ Annotation annotation = adapter.getConverterAnnotation(resourceAttribute);
+ if (annotation != null) {
+ return new SimpleAssociation<JavaConverter.Adapter, Annotation>(adapter, annotation);
+ }
+ }
+ return null;
+ }
+
+ protected JavaConverter buildNullConverter() {
+ return new NullJavaConverter(this);
+ }
+
+
+ // ********** converter adapters **********
+
+ /**
+ * Return the converter adapter for the specified converter type.
+ */
+ protected JavaConverter.Adapter getConverterAdapter(Class<? extends Converter> converterType) {
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter.getConverterType() == converterType) {
+ return adapter;
+ }
+ }
+ return null;
+ }
+
+ protected Iterable<JavaConverter.Adapter> getConverterAdapters() {
+ return CONVERTER_ADAPTERS;
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return BasicAnnotation.ANNOTATION_NAME;
+ }
+
+ @Override
+ public boolean isOverridableAttributeMapping() {
+ return true;
+ }
+
+
+ // ********** JavaColumn.Owner implementation **********
+
+ public ColumnAnnotation getColumnAnnotation() {
+ return (ColumnAnnotation) this.getResourcePersistentAttribute().getNonNullAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeColumnAnnotation() {
+ this.getResourcePersistentAttribute().removeAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public String getDefaultColumnName() {
+ return this.getName();
+ }
+
+ public String getDefaultTableName() {
+ return this.getTypeMapping().getPrimaryTableName();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return this.getTypeMapping().allAssociatedTableNames();
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new NamedColumnValidator((BaseColumn) column, (BaseColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider());
+ }
+
+
+ // ********** 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.column.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ result = this.converter.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.column.validate(messages, reporter, astRoot);
+ this.converter.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMappingDefinition.java
new file mode 100644
index 0000000000..e9db78d75f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaBasicMappingDefinition.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.BasicAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.EnumeratedAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.LobAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TemporalAnnotation;
+
+public abstract class AbstractJavaBasicMappingDefinition
+ implements DefaultJavaAttributeMappingDefinition
+{
+ protected AbstractJavaBasicMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return BasicAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ ColumnAnnotation.ANNOTATION_NAME,
+ LobAnnotation.ANNOTATION_NAME,
+ TemporalAnnotation.ANNOTATION_NAME,
+ EnumeratedAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaBasicMapping(persistentAttribute);
+ }
+
+ public boolean isDefault(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.typeIsBasic();
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddable.java
new file mode 100644
index 0000000000..991d67b0d2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddable.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaEmbeddable;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.resource.java.EmbeddableAnnotation;
+
+/**
+ * Java embeddable type mapping
+ */
+public abstract class AbstractJavaEmbeddable
+ extends AbstractJavaTypeMapping<EmbeddableAnnotation>
+ implements JavaEmbeddable
+{
+ protected AbstractJavaEmbeddable(JavaPersistentType parent, EmbeddableAnnotation mappingAnnotation) {
+ super(parent, mappingAnnotation);
+ }
+
+ public String getKey() {
+ return MappingKeys.EMBEDDABLE_TYPE_MAPPING_KEY;
+ }
+
+ public JavaPersistentType getIdClass() {
+ return null;
+ }
+
+ public boolean isMapped() {
+ return true;
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return false;
+ }
+
+ @Override
+ public boolean validatesAgainstDatabase() {
+ return false;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddedMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddedMappingDefinition.java
new file mode 100644
index 0000000000..4460a740a3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEmbeddedMappingDefinition.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverrideAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverridesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.EmbeddedAnnotation;
+
+public abstract class AbstractJavaEmbeddedMappingDefinition
+ implements DefaultJavaAttributeMappingDefinition
+{
+ protected AbstractJavaEmbeddedMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return EmbeddedAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ AttributeOverrideAnnotation.ANNOTATION_NAME,
+ AttributeOverridesAnnotation.ANNOTATION_NAME,
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaEmbeddedMapping(persistentAttribute);
+ }
+
+ public boolean isDefault(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getEmbeddable() != null;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEntity.java
new file mode 100644
index 0000000000..11157f3cb5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaEntity.java
@@ -0,0 +1,1816 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import java.util.Collection;
+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.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.HashBag;
+import org.eclipse.jpt.common.utility.internal.NotNullFilter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SingleElementListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SubIterableWrapper;
+import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.JpaPlatformVariation.Supported;
+import org.eclipse.jpt.jpa.core.context.AssociationOverride;
+import org.eclipse.jpt.jpa.core.context.AssociationOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.AttributeOverride;
+import org.eclipse.jpt.jpa.core.context.AttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.BaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.Column;
+import org.eclipse.jpt.jpa.core.context.DiscriminatorColumn;
+import org.eclipse.jpt.jpa.core.context.DiscriminatorType;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.InheritanceType;
+import org.eclipse.jpt.jpa.core.context.JoinColumn;
+import org.eclipse.jpt.jpa.core.context.JoinTable;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.OverrideContainer;
+import org.eclipse.jpt.jpa.core.context.Override_;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.PrimaryKeyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyTable;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.SecondaryTable;
+import org.eclipse.jpt.jpa.core.context.Table;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.JoinColumn.Owner;
+import org.eclipse.jpt.jpa.core.context.java.JavaAssociationOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaDiscriminatorColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaEntity;
+import org.eclipse.jpt.jpa.core.context.java.JavaGeneratorContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaIdClassReference;
+import org.eclipse.jpt.jpa.core.context.java.JavaNamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaQueryContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaSecondaryTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.EntityTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AssociationOverrideInverseJoinColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AssociationOverrideJoinColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AssociationOverrideJoinTableValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AssociationOverrideValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AttributeOverrideColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.AttributeOverrideValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.DiscriminatorColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityPrimaryKeyJoinColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericEntityPrimaryKeyValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinTableTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.MappedSuperclassOverrideDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.SecondaryTableValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.TableValidator;
+import org.eclipse.jpt.jpa.core.internal.resource.java.NullPrimaryKeyJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.jpa2.context.SingleRelationshipMapping2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaCacheableHolder2_0;
+import org.eclipse.jpt.jpa.core.resource.java.DiscriminatorValueAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.EntityAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.InheritanceAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
+import org.eclipse.jpt.jpa.core.resource.java.NestableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SecondaryTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SecondaryTablesAnnotation;
+import org.eclipse.jpt.jpa.db.Schema;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java entity
+ */
+public abstract class AbstractJavaEntity
+ extends AbstractJavaTypeMapping<EntityAnnotation>
+ implements JavaEntity, JavaCacheableHolder2_0, JavaGeneratorContainer.Owner, JavaQueryContainer.Owner
+{
+ protected String specifiedName;
+ protected String defaultName;
+
+ protected Entity rootEntity;
+ protected final Vector<Entity> descendants = new Vector<Entity>();
+
+ protected final JavaIdClassReference idClassReference;
+
+ protected final JavaTable table;
+ protected boolean specifiedTableIsAllowed;
+ protected boolean tableIsUndefined;
+
+ protected final Vector<JavaSecondaryTable> specifiedSecondaryTables = new Vector<JavaSecondaryTable>();
+ protected final SpecifiedSecondaryTableContainerAdapter specifiedSecondaryTableContainerAdapter = new SpecifiedSecondaryTableContainerAdapter();
+ protected final Table.Owner specifiedSecondaryTableOwner;
+
+ protected final PrimaryKeyJoinColumnOwner primaryKeyJoinColumnOwner;
+ protected final Vector<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns = new Vector<JavaPrimaryKeyJoinColumn>();
+ protected final SpecifiedPrimaryKeyJoinColumnContainerAdapter specifiedPrimaryKeyJoinColumnContainerAdapter = new SpecifiedPrimaryKeyJoinColumnContainerAdapter();
+ protected JavaPrimaryKeyJoinColumn defaultPrimaryKeyJoinColumn;
+
+ protected InheritanceType specifiedInheritanceStrategy;
+ protected InheritanceType defaultInheritanceStrategy;
+
+ protected String specifiedDiscriminatorValue;
+ protected String defaultDiscriminatorValue;
+ protected boolean specifiedDiscriminatorValueIsAllowed;
+ protected boolean discriminatorValueIsUndefined;
+
+ protected final JavaDiscriminatorColumn discriminatorColumn;
+ protected boolean specifiedDiscriminatorColumnIsAllowed;
+ protected boolean discriminatorColumnIsUndefined;
+
+ protected final JavaAttributeOverrideContainer attributeOverrideContainer;
+ protected final JavaAssociationOverrideContainer associationOverrideContainer;
+
+ protected final JavaGeneratorContainer generatorContainer;
+ protected final JavaQueryContainer queryContainer;
+
+
+ // ********** construction **********
+
+ protected AbstractJavaEntity(JavaPersistentType parent, EntityAnnotation mappingAnnotation) {
+ super(parent, mappingAnnotation);
+ this.specifiedName = this.mappingAnnotation.getName();
+ this.idClassReference = this.buildIdClassReference();
+ this.table = this.buildTable();
+ this.specifiedSecondaryTableOwner = this.buildSpecifiedSecondaryTableOwner();
+ this.initializeSpecifiedSecondaryTables();
+ this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner();
+ this.initializeSpecifiedPrimaryKeyJoinColumns();
+ this.specifiedInheritanceStrategy = this.buildSpecifiedInheritanceStrategy();
+ this.specifiedDiscriminatorValue = this.getDiscriminatorValueAnnotation().getValue();
+ this.discriminatorColumn = this.buildDiscriminatorColumn();
+ // start with the entity as the root - it will be recalculated in update()
+ this.rootEntity = this;
+ this.attributeOverrideContainer = this.buildAttributeOverrideContainer();
+ this.associationOverrideContainer = this.buildAssociationOverrideContainer();
+ this.generatorContainer = this.buildGeneratorContainer();
+ this.queryContainer = this.buildQueryContainer();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedName_(this.mappingAnnotation.getName());
+ this.idClassReference.synchronizeWithResourceModel();
+ this.table.synchronizeWithResourceModel();
+ this.syncSpecifiedSecondaryTables();
+ this.syncSpecifiedPrimaryKeyJoinColumns();
+ this.setSpecifiedInheritanceStrategy_(this.buildSpecifiedInheritanceStrategy());
+ this.setSpecifiedDiscriminatorValue_(this.getDiscriminatorValueAnnotation().getValue());
+ this.discriminatorColumn.synchronizeWithResourceModel();
+ this.attributeOverrideContainer.synchronizeWithResourceModel();
+ this.associationOverrideContainer.synchronizeWithResourceModel();
+ this.generatorContainer.synchronizeWithResourceModel();
+ this.queryContainer.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+
+ this.setDefaultName(this.buildDefaultName());
+
+ // calculate root entity early - other things depend on it
+ this.setRootEntity(this.buildRootEntity());
+ this.updateDescendants();
+
+ this.idClassReference.update();
+
+ this.table.update();
+ this.setSpecifiedTableIsAllowed(this.buildSpecifiedTableIsAllowed());
+ this.setTableIsUndefined(this.buildTableIsUndefined());
+
+ this.updateNodes(this.getSecondaryTables());
+
+ this.updateDefaultPrimaryKeyJoinColumn();
+ this.updateNodes(this.getPrimaryKeyJoinColumns());
+
+ this.setDefaultInheritanceStrategy(this.buildDefaultInheritanceStrategy());
+
+ this.setDefaultDiscriminatorValue(this.buildDefaultDiscriminatorValue());
+ this.setSpecifiedDiscriminatorValueIsAllowed(this.buildSpecifiedDiscriminatorValueIsAllowed());
+ this.setDiscriminatorValueIsUndefined(this.buildDiscriminatorValueIsUndefined());
+
+ this.discriminatorColumn.update();
+ this.setSpecifiedDiscriminatorColumnIsAllowed(this.buildSpecifiedDiscriminatorColumnIsAllowed());
+ this.setDiscriminatorColumnIsUndefined(this.buildDiscriminatorColumnIsUndefined());
+
+ this.attributeOverrideContainer.update();
+ this.associationOverrideContainer.update();
+
+ this.generatorContainer.update();
+ this.queryContainer.update();
+ }
+
+
+ // ********** name **********
+
+ @Override
+ public String getName() {
+ return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
+ }
+
+ public String getSpecifiedName() {
+ return this.specifiedName;
+ }
+
+ public void setSpecifiedName(String name) {
+ this.mappingAnnotation.setName(name);
+ this.setSpecifiedName_(name);
+ }
+
+ protected void setSpecifiedName_(String name) {
+ String old = this.specifiedName;
+ this.specifiedName = name;
+ this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
+ }
+
+ public String getDefaultName() {
+ return this.defaultName;
+ }
+
+ protected void setDefaultName(String name) {
+ String old = this.defaultName;
+ this.defaultName = name;
+ this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildDefaultName() {
+ return this.getResourcePersistentType().getName();
+ }
+
+
+ // ********** root entity **********
+
+ public Entity getRootEntity() {
+ return this.rootEntity;
+ }
+
+ protected void setRootEntity(Entity entity) {
+ Entity old = this.rootEntity;
+ this.rootEntity = entity;
+ this.firePropertyChanged(ROOT_ENTITY_PROPERTY, old, entity);
+ }
+
+ protected Entity buildRootEntity() {
+ Entity root = this;
+ for (TypeMapping typeMapping : this.getAncestors()) {
+ if (typeMapping instanceof Entity) {
+ root = (Entity) typeMapping;
+ }
+ }
+ return root;
+ }
+
+
+ // ********** descendants **********
+
+ public Iterable<Entity> getDescendants() {
+ return new LiveCloneListIterable<Entity>(this.descendants);
+ }
+
+ protected void updateDescendants() {
+ this.synchronizeCollection(this.buildDescendants(), this.descendants, DESCENDANTS_COLLECTION);
+ }
+
+ protected Iterable<Entity> buildDescendants() {
+ return new FilteringIterable<Entity>(this.getPersistenceUnit().getEntities()) {
+ @Override
+ protected boolean accept(Entity entity) {
+ return AbstractJavaEntity.this.entityIsDescendant(entity);
+ }
+ };
+ }
+
+ /**
+ * Return whether specified entity is a descendant of the entity.
+ */
+ protected boolean entityIsDescendant(Entity entity) {
+ String typeName = this.getPersistentType().getName();
+ String entityTypeName = entity.getPersistentType().getName();
+ String rootEntityTypeName = entity.getRootEntity().getPersistentType().getName();
+ return Tools.valuesAreDifferent(typeName, entityTypeName) &&
+ Tools.valuesAreEqual(typeName, rootEntityTypeName);
+ }
+
+
+ // ********** id class **********
+
+ public JavaIdClassReference getIdClassReference() {
+ return this.idClassReference;
+ }
+
+ protected JavaIdClassReference buildIdClassReference() {
+ return new GenericJavaIdClassReference(this);
+ }
+
+ public JavaPersistentType getIdClass() {
+ return this.idClassReference.getIdClass();
+ }
+
+
+ // ********** table **********
+
+ public JavaTable getTable() {
+ return this.table;
+ }
+
+ protected JavaTable buildTable() {
+ return this.getJpaFactory().buildJavaTable(this, this.buildTableOwner());
+ }
+
+ protected JavaTable.Owner buildTableOwner() {
+ return new TableOwner();
+ }
+
+ public boolean specifiedTableIsAllowed() {
+ return this.specifiedTableIsAllowed;
+ }
+
+ protected void setSpecifiedTableIsAllowed(boolean specifiedTableIsAllowed) {
+ boolean old = this.specifiedTableIsAllowed;
+ this.specifiedTableIsAllowed = specifiedTableIsAllowed;
+ this.firePropertyChanged(SPECIFIED_TABLE_IS_ALLOWED_PROPERTY, old, specifiedTableIsAllowed);
+ }
+
+ protected boolean buildSpecifiedTableIsAllowed() {
+ return ! this.isAbstractTablePerClass() && ! this.isSingleTableDescendant();
+ }
+
+ public boolean tableIsUndefined() {
+ return this.tableIsUndefined;
+ }
+
+ protected void setTableIsUndefined(boolean tableIsUndefined) {
+ boolean old = this.tableIsUndefined;
+ this.tableIsUndefined = tableIsUndefined;
+ this.firePropertyChanged(TABLE_IS_UNDEFINED_PROPERTY, old, tableIsUndefined);
+ }
+
+ protected boolean buildTableIsUndefined() {
+ return this.isAbstractTablePerClass();
+ }
+
+ /**
+ * <ul>
+ * <li>If the entity is part of a single table inheritance hierarchy, the table
+ * name defaults to the root entity's table name.
+ * <li>If the entity is abstract and part of a table per class
+ * inheritance hierarchy, the table name defaults to null, as no table applies.
+ * <li>Otherwise, the table name defaults to the entity name.
+ * </ul>
+ */
+ public String getDefaultTableName() {
+ return this.isSingleTableDescendant() ?
+ this.rootEntity.getTable().getName() :
+ this.isAbstractTablePerClass() ? null : this.getName();
+ }
+
+ /**
+ * @see #getDefaultTableName()
+ */
+ public String getDefaultSchema() {
+ return this.isSingleTableDescendant() ?
+ this.rootEntity.getTable().getSchema() :
+ this.isAbstractTablePerClass() ? null : this.getContextDefaultSchema();
+ }
+
+ /**
+ * @see #getDefaultTableName()
+ */
+ public String getDefaultCatalog() {
+ return this.isSingleTableDescendant() ?
+ this.rootEntity.getTable().getCatalog() :
+ this.isAbstractTablePerClass() ? null : this.getContextDefaultCatalog();
+ }
+
+
+ // ********** secondary tables **********
+
+ public ListIterator<JavaSecondaryTable> secondaryTables() {
+ return this.specifiedSecondaryTables();
+ }
+
+ protected ListIterable<JavaSecondaryTable> getSecondaryTables() {
+ return this.getSpecifiedSecondaryTables();
+ }
+
+ public int secondaryTablesSize() {
+ return this.specifiedSecondaryTablesSize();
+ }
+
+
+ // ********** specified secondary tables **********
+
+ public ListIterator<JavaSecondaryTable> specifiedSecondaryTables() {
+ return this.getSpecifiedSecondaryTables().iterator();
+ }
+
+ protected ListIterable<JavaSecondaryTable> getSpecifiedSecondaryTables() {
+ return new LiveCloneListIterable<JavaSecondaryTable>(this.specifiedSecondaryTables);
+ }
+
+ public int specifiedSecondaryTablesSize() {
+ return this.specifiedSecondaryTables.size();
+ }
+
+ public JavaSecondaryTable addSpecifiedSecondaryTable() {
+ return this.addSpecifiedSecondaryTable(this.specifiedSecondaryTables.size());
+ }
+
+ public JavaSecondaryTable addSpecifiedSecondaryTable(int index) {
+ SecondaryTableAnnotation annotation = this.buildSecondaryTableAnnotation(index);
+ return this.addSpecifiedSecondaryTable_(index, annotation);
+ }
+
+ protected SecondaryTableAnnotation buildSecondaryTableAnnotation(int index) {
+ return (SecondaryTableAnnotation) this.getResourcePersistentType().addAnnotation(index, SecondaryTableAnnotation.ANNOTATION_NAME, SecondaryTablesAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeSpecifiedSecondaryTable(SecondaryTable secondaryTable) {
+ this.removeSpecifiedSecondaryTable(this.specifiedSecondaryTables.indexOf(secondaryTable));
+ }
+
+ public void removeSpecifiedSecondaryTable(int index) {
+ this.getResourcePersistentType().removeAnnotation(index, SecondaryTableAnnotation.ANNOTATION_NAME, SecondaryTablesAnnotation.ANNOTATION_NAME);
+ this.removeSpecifiedSecondaryTable_(index);
+ }
+
+ protected void removeSpecifiedSecondaryTable_(int index) {
+ this.removeItemFromList(index, this.specifiedSecondaryTables, SPECIFIED_SECONDARY_TABLES_LIST);
+ }
+
+ public void moveSpecifiedSecondaryTable(int targetIndex, int sourceIndex) {
+ this.getResourceAnnotatedElement().moveAnnotation(targetIndex, sourceIndex, SecondaryTablesAnnotation.ANNOTATION_NAME);
+ this.moveItemInList(targetIndex, sourceIndex, this.specifiedSecondaryTables, SPECIFIED_SECONDARY_TABLES_LIST);
+ }
+
+ protected void initializeSpecifiedSecondaryTables() {
+ for (SecondaryTableAnnotation annotation : this.getSecondaryTableAnnotations()) {
+ this.specifiedSecondaryTables.add(this.buildSecondaryTable(annotation));
+ }
+ }
+
+ protected JavaSecondaryTable buildSecondaryTable(SecondaryTableAnnotation secondaryTableAnnotation) {
+ return this.getJpaFactory().buildJavaSecondaryTable(this, this.specifiedSecondaryTableOwner, secondaryTableAnnotation);
+ }
+
+ protected void syncSpecifiedSecondaryTables() {
+ ContextContainerTools.synchronizeWithResourceModel(this.specifiedSecondaryTableContainerAdapter);
+ }
+
+ protected Iterable<SecondaryTableAnnotation> getSecondaryTableAnnotations() {
+ return new SubIterableWrapper<NestableAnnotation, SecondaryTableAnnotation>(
+ CollectionTools.iterable(this.secondaryTableAnnotations())
+ );
+ }
+
+ protected Iterator<NestableAnnotation> secondaryTableAnnotations() {
+ return this.getResourceAnnotatedElement().annotations(SecondaryTableAnnotation.ANNOTATION_NAME, SecondaryTablesAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void moveSpecifiedSecondaryTable_(int index, JavaSecondaryTable secondaryTable) {
+ this.moveItemInList(index, secondaryTable, this.specifiedSecondaryTables, SPECIFIED_SECONDARY_TABLES_LIST);
+ }
+
+ protected JavaSecondaryTable addSpecifiedSecondaryTable_(int index, SecondaryTableAnnotation secondaryTableAnnotation) {
+ JavaSecondaryTable secondaryTable = this.buildSecondaryTable(secondaryTableAnnotation);
+ this.addItemToList(index, secondaryTable, this.specifiedSecondaryTables, SPECIFIED_SECONDARY_TABLES_LIST);
+ return secondaryTable;
+ }
+
+ protected void removeSpecifiedSecondaryTable_(JavaSecondaryTable secondaryTable) {
+ this.removeSpecifiedSecondaryTable_(this.specifiedSecondaryTables.indexOf(secondaryTable));
+ }
+
+ /**
+ * specified secondary table container adapter
+ */
+ protected class SpecifiedSecondaryTableContainerAdapter
+ implements ContextContainerTools.Adapter<JavaSecondaryTable, SecondaryTableAnnotation>
+ {
+ public Iterable<JavaSecondaryTable> getContextElements() {
+ return AbstractJavaEntity.this.getSpecifiedSecondaryTables();
+ }
+ public Iterable<SecondaryTableAnnotation> getResourceElements() {
+ return AbstractJavaEntity.this.getSecondaryTableAnnotations();
+ }
+ public SecondaryTableAnnotation getResourceElement(JavaSecondaryTable contextElement) {
+ return contextElement.getTableAnnotation();
+ }
+ public void moveContextElement(int index, JavaSecondaryTable element) {
+ AbstractJavaEntity.this.moveSpecifiedSecondaryTable_(index, element);
+ }
+ public void addContextElement(int index, SecondaryTableAnnotation resourceElement) {
+ AbstractJavaEntity.this.addSpecifiedSecondaryTable_(index, resourceElement);
+ }
+ public void removeContextElement(JavaSecondaryTable element) {
+ AbstractJavaEntity.this.removeSpecifiedSecondaryTable_(element);
+ }
+ }
+
+ protected Table.Owner buildSpecifiedSecondaryTableOwner() {
+ return new SecondaryTableOwner();
+ }
+
+
+ // ********** primary key join columns **********
+
+ public ListIterator<JavaPrimaryKeyJoinColumn> primaryKeyJoinColumns() {
+ return this.getPrimaryKeyJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaPrimaryKeyJoinColumn> getPrimaryKeyJoinColumns() {
+ return this.hasSpecifiedPrimaryKeyJoinColumns() ? this.getSpecifiedPrimaryKeyJoinColumns() : this.getDefaultPrimaryKeyJoinColumns();
+ }
+
+ public int primaryKeyJoinColumnsSize() {
+ return this.hasSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumnsSize() : this.defaultPrimaryKeyJoinColumnsSize();
+ }
+
+
+ // ********** specified primary key join columns **********
+
+ public ListIterator<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns() {
+ return this.getSpecifiedPrimaryKeyJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaPrimaryKeyJoinColumn> getSpecifiedPrimaryKeyJoinColumns() {
+ return new LiveCloneListIterable<JavaPrimaryKeyJoinColumn>(this.specifiedPrimaryKeyJoinColumns);
+ }
+
+ public int specifiedPrimaryKeyJoinColumnsSize() {
+ return this.specifiedPrimaryKeyJoinColumns.size();
+ }
+
+ protected boolean hasSpecifiedPrimaryKeyJoinColumns() {
+ return this.specifiedPrimaryKeyJoinColumns.size() != 0;
+ }
+
+ public JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn() {
+ return this.addSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.size());
+ }
+
+ public JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn(int index) {
+ PrimaryKeyJoinColumnAnnotation annotation = this.buildPrimaryKeyJoinColumnAnnotation(index);
+ return this.addSpecifiedPrimaryKeyJoinColumn_(index, annotation);
+ }
+
+ protected PrimaryKeyJoinColumnAnnotation buildPrimaryKeyJoinColumnAnnotation(int index) {
+ return (PrimaryKeyJoinColumnAnnotation) this.getResourcePersistentType().addAnnotation(index, PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeSpecifiedPrimaryKeyJoinColumn(PrimaryKeyJoinColumn primaryKeyJoinColumn) {
+ this.removeSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.indexOf(primaryKeyJoinColumn));
+ }
+
+ public void removeSpecifiedPrimaryKeyJoinColumn(int index) {
+ this.getResourcePersistentType().removeAnnotation(index, PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ this.removeSpecifiedPrimaryKeyJoinColumn_(index);
+ }
+
+ protected void removeSpecifiedPrimaryKeyJoinColumn_(int index) {
+ this.removeItemFromList(index, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ public void moveSpecifiedPrimaryKeyJoinColumn(int targetIndex, int sourceIndex) {
+ this.getResourcePersistentType().moveAnnotation(targetIndex, sourceIndex, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ this.moveItemInList(targetIndex, sourceIndex, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ protected PrimaryKeyJoinColumnOwner buildPrimaryKeyJoinColumnOwner() {
+ return new PrimaryKeyJoinColumnOwner();
+ }
+
+ protected void initializeSpecifiedPrimaryKeyJoinColumns() {
+ for (PrimaryKeyJoinColumnAnnotation annotation : this.getPrimaryKeyJoinColumnAnnotations()) {
+ this.specifiedPrimaryKeyJoinColumns.add(this.buildPrimaryKeyJoinColumn(annotation));
+ }
+ }
+
+ protected JavaPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(PrimaryKeyJoinColumnAnnotation primaryKeyJoinColumnAnnotation) {
+ return this.getJpaFactory().buildJavaPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner, primaryKeyJoinColumnAnnotation);
+ }
+
+ protected void syncSpecifiedPrimaryKeyJoinColumns() {
+ ContextContainerTools.synchronizeWithResourceModel(this.specifiedPrimaryKeyJoinColumnContainerAdapter);
+ }
+
+ protected Iterable<PrimaryKeyJoinColumnAnnotation> getPrimaryKeyJoinColumnAnnotations() {
+ return new SubIterableWrapper<NestableAnnotation, PrimaryKeyJoinColumnAnnotation>(
+ CollectionTools.iterable(this.primaryKeyJoinColumnAnnotations())
+ );
+ }
+
+ protected Iterator<NestableAnnotation> primaryKeyJoinColumnAnnotations() {
+ return this.getResourceAnnotatedElement().annotations(PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void moveSpecifiedPrimaryKeyJoinColumn_(int index, JavaPrimaryKeyJoinColumn primaryKeyJoinColumn) {
+ this.moveItemInList(index, primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ protected JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn_(int index, PrimaryKeyJoinColumnAnnotation primaryKeyJoinColumnAnnotation) {
+ JavaPrimaryKeyJoinColumn primaryKeyJoinColumn = this.buildPrimaryKeyJoinColumn(primaryKeyJoinColumnAnnotation);
+ this.addItemToList(index, primaryKeyJoinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ return primaryKeyJoinColumn;
+ }
+
+ protected void removeSpecifiedPrimaryKeyJoinColumn_(JavaPrimaryKeyJoinColumn primaryKeyJoinColumn) {
+ this.removeSpecifiedPrimaryKeyJoinColumn_(this.specifiedPrimaryKeyJoinColumns.indexOf(primaryKeyJoinColumn));
+ }
+
+ /**
+ * specified primary key join column container adapter
+ */
+ protected class SpecifiedPrimaryKeyJoinColumnContainerAdapter
+ implements ContextContainerTools.Adapter<JavaPrimaryKeyJoinColumn, PrimaryKeyJoinColumnAnnotation>
+ {
+ public Iterable<JavaPrimaryKeyJoinColumn> getContextElements() {
+ return AbstractJavaEntity.this.getSpecifiedPrimaryKeyJoinColumns();
+ }
+ public Iterable<PrimaryKeyJoinColumnAnnotation> getResourceElements() {
+ return AbstractJavaEntity.this.getPrimaryKeyJoinColumnAnnotations();
+ }
+ public PrimaryKeyJoinColumnAnnotation getResourceElement(JavaPrimaryKeyJoinColumn contextElement) {
+ return contextElement.getColumnAnnotation();
+ }
+ public void moveContextElement(int index, JavaPrimaryKeyJoinColumn element) {
+ AbstractJavaEntity.this.moveSpecifiedPrimaryKeyJoinColumn_(index, element);
+ }
+ public void addContextElement(int index, PrimaryKeyJoinColumnAnnotation resourceElement) {
+ AbstractJavaEntity.this.addSpecifiedPrimaryKeyJoinColumn_(index, resourceElement);
+ }
+ public void removeContextElement(JavaPrimaryKeyJoinColumn element) {
+ AbstractJavaEntity.this.removeSpecifiedPrimaryKeyJoinColumn_(element);
+ }
+ }
+
+
+ // ********** default primary key join column **********
+
+ public JavaPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() {
+ return this.defaultPrimaryKeyJoinColumn;
+ }
+
+ protected void setDefaultPrimaryKeyJoinColumn(JavaPrimaryKeyJoinColumn pkJoinColumn) {
+ JavaPrimaryKeyJoinColumn old = this.defaultPrimaryKeyJoinColumn;
+ this.defaultPrimaryKeyJoinColumn = pkJoinColumn;
+ this.firePropertyChanged(DEFAULT_PRIMARY_KEY_JOIN_COLUMN_PROPERTY, old, pkJoinColumn);
+ }
+
+ protected ListIterable<JavaPrimaryKeyJoinColumn> getDefaultPrimaryKeyJoinColumns() {
+ return (this.defaultPrimaryKeyJoinColumn != null) ?
+ new SingleElementListIterable<JavaPrimaryKeyJoinColumn>(this.defaultPrimaryKeyJoinColumn) :
+ EmptyListIterable.<JavaPrimaryKeyJoinColumn>instance();
+ }
+
+ protected int defaultPrimaryKeyJoinColumnsSize() {
+ return (this.defaultPrimaryKeyJoinColumn == null) ? 0 : 1;
+ }
+
+ protected void updateDefaultPrimaryKeyJoinColumn() {
+ if (this.buildsDefaultPrimaryKeyJoinColumn()) {
+ if (this.defaultPrimaryKeyJoinColumn == null) {
+ this.setDefaultPrimaryKeyJoinColumn(this.buildDefaultPrimaryKeyJoinColumn());
+ } else {
+ this.defaultPrimaryKeyJoinColumn.update();
+ }
+ } else {
+ this.setDefaultPrimaryKeyJoinColumn(null);
+ }
+ }
+
+ protected boolean buildsDefaultPrimaryKeyJoinColumn() {
+ return ! this.hasSpecifiedPrimaryKeyJoinColumns();
+ }
+
+ protected JavaPrimaryKeyJoinColumn buildDefaultPrimaryKeyJoinColumn() {
+ return this.buildPrimaryKeyJoinColumn(new NullPrimaryKeyJoinColumnAnnotation(this.getResourcePersistentType()));
+ }
+
+
+ // ********** inheritance strategy **********
+
+ public InheritanceType getInheritanceStrategy() {
+ return (this.specifiedInheritanceStrategy != null) ? this.specifiedInheritanceStrategy : this.defaultInheritanceStrategy;
+ }
+
+ public InheritanceType getSpecifiedInheritanceStrategy() {
+ return this.specifiedInheritanceStrategy;
+ }
+
+ public void setSpecifiedInheritanceStrategy(InheritanceType inheritanceType) {
+ if (this.valuesAreDifferent(this.specifiedInheritanceStrategy, inheritanceType)) {
+ this.getInheritanceAnnotation().setStrategy(InheritanceType.toJavaResourceModel(inheritanceType));
+ this.removeInheritanceAnnotationIfUnset();
+ this.setSpecifiedInheritanceStrategy_(inheritanceType);
+ }
+ }
+
+ protected void setSpecifiedInheritanceStrategy_(InheritanceType inheritanceType) {
+ InheritanceType old = this.specifiedInheritanceStrategy;
+ this.specifiedInheritanceStrategy = inheritanceType;
+ this.firePropertyChanged(SPECIFIED_INHERITANCE_STRATEGY_PROPERTY, old, inheritanceType);
+ }
+
+ protected InheritanceType buildSpecifiedInheritanceStrategy() {
+ return InheritanceType.fromJavaResourceModel(this.getInheritanceAnnotation().getStrategy());
+ }
+
+ public InheritanceType getDefaultInheritanceStrategy() {
+ return this.defaultInheritanceStrategy;
+ }
+
+ protected void setDefaultInheritanceStrategy(InheritanceType inheritanceType) {
+ InheritanceType old = this.defaultInheritanceStrategy;
+ this.defaultInheritanceStrategy = inheritanceType;
+ this.firePropertyChanged(DEFAULT_INHERITANCE_STRATEGY_PROPERTY, old, inheritanceType);
+ }
+
+ protected InheritanceType buildDefaultInheritanceStrategy() {
+ return this.isRoot() ? InheritanceType.SINGLE_TABLE : this.rootEntity.getInheritanceStrategy();
+ }
+
+
+ // ********** inheritance annotation **********
+
+ protected InheritanceAnnotation getInheritanceAnnotation() {
+ return (InheritanceAnnotation) this.getResourcePersistentType().getNonNullAnnotation(InheritanceAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void removeInheritanceAnnotationIfUnset() {
+ if (this.getInheritanceAnnotation().isUnset()) {
+ this.removeInheritanceAnnotation();
+ }
+ }
+
+ protected void removeInheritanceAnnotation() {
+ this.getResourcePersistentType().removeAnnotation(InheritanceAnnotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** discriminator value **********
+
+ public String getDiscriminatorValue() {
+ return (this.specifiedDiscriminatorValue != null) ? this.specifiedDiscriminatorValue : this.defaultDiscriminatorValue;
+ }
+
+ public String getSpecifiedDiscriminatorValue() {
+ return this.specifiedDiscriminatorValue;
+ }
+
+ public void setSpecifiedDiscriminatorValue(String discriminatorValue) {
+ if (this.valuesAreDifferent(this.specifiedDiscriminatorValue, discriminatorValue)) {
+ this.getDiscriminatorValueAnnotation().setValue(discriminatorValue);
+ this.removeDiscriminatorValueAnnotationIfUnset();
+ this.setSpecifiedDiscriminatorValue_(discriminatorValue);
+ }
+ }
+
+ protected void setSpecifiedDiscriminatorValue_(String discriminatorValue) {
+ String old = this.specifiedDiscriminatorValue;
+ this.specifiedDiscriminatorValue = discriminatorValue;
+ this.firePropertyChanged(SPECIFIED_DISCRIMINATOR_VALUE_PROPERTY, old, discriminatorValue);
+ }
+
+ public String getDefaultDiscriminatorValue() {
+ return this.defaultDiscriminatorValue;
+ }
+
+ protected void setDefaultDiscriminatorValue(String discriminatorValue) {
+ String old = this.defaultDiscriminatorValue;
+ this.defaultDiscriminatorValue = discriminatorValue;
+ this.firePropertyChanged(DEFAULT_DISCRIMINATOR_VALUE_PROPERTY, old, discriminatorValue);
+ }
+
+ /**
+ * From the Spec:
+ * If the DiscriminatorValue annotation is not specified, a
+ * provider-specific function to generate a value representing
+ * the entity type is used for the value of the discriminator
+ * column. If the DiscriminatorType is STRING, the discriminator
+ * value default is the entity name.
+ */
+ // TODO extension point for provider-specific function?
+ protected String buildDefaultDiscriminatorValue() {
+ if (this.discriminatorValueIsUndefined) {
+ return null;
+ }
+ return (this.getDiscriminatorType() == DiscriminatorType.STRING) ? this.getName() : null;
+ }
+
+ protected DiscriminatorType getDiscriminatorType() {
+ return this.discriminatorColumn.getDiscriminatorType();
+ }
+
+ public boolean specifiedDiscriminatorValueIsAllowed() {
+ return this.specifiedDiscriminatorValueIsAllowed;
+ }
+
+ protected void setSpecifiedDiscriminatorValueIsAllowed(boolean allowed) {
+ boolean old = this.specifiedDiscriminatorValueIsAllowed;
+ this.specifiedDiscriminatorValueIsAllowed = allowed;
+ this.firePropertyChanged(SPECIFIED_DISCRIMINATOR_VALUE_IS_ALLOWED_PROPERTY, old, allowed);
+ }
+
+ protected boolean buildSpecifiedDiscriminatorValueIsAllowed() {
+ return ! this.isTablePerClass() && ! this.isAbstract();
+ }
+
+ public boolean discriminatorValueIsUndefined() {
+ return this.discriminatorValueIsUndefined;
+ }
+
+ protected void setDiscriminatorValueIsUndefined(boolean undefined) {
+ boolean old = this.discriminatorValueIsUndefined;
+ this.discriminatorValueIsUndefined = undefined;
+ this.firePropertyChanged(DISCRIMINATOR_VALUE_IS_UNDEFINED_PROPERTY, old, undefined);
+ }
+
+ protected boolean buildDiscriminatorValueIsUndefined() {
+ return this.isTablePerClass() ||
+ this.isAbstract() ||
+ this.isRootNoDescendantsNoStrategyDefined();
+ }
+
+
+ // ********** discriminator value annotation **********
+
+ protected DiscriminatorValueAnnotation getDiscriminatorValueAnnotation() {
+ return (DiscriminatorValueAnnotation) this.getResourcePersistentType().getNonNullAnnotation(DiscriminatorValueAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void removeDiscriminatorValueAnnotationIfUnset() {
+ if (this.getDiscriminatorValueAnnotation().isUnset()) {
+ this.removeDiscriminatorValueAnnotation();
+ }
+ }
+
+ protected void removeDiscriminatorValueAnnotation() {
+ this.getResourcePersistentType().removeAnnotation(DiscriminatorValueAnnotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** discriminator column **********
+
+ public JavaDiscriminatorColumn getDiscriminatorColumn() {
+ return this.discriminatorColumn;
+ }
+
+ protected JavaDiscriminatorColumn buildDiscriminatorColumn() {
+ return this.getJpaFactory().buildJavaDiscriminatorColumn(this, this.buildDiscriminatorColumnOwner());
+ }
+
+ protected JavaDiscriminatorColumn.Owner buildDiscriminatorColumnOwner() {
+ return new DiscriminatorColumnOwner();
+ }
+
+ public boolean specifiedDiscriminatorColumnIsAllowed() {
+ return this.specifiedDiscriminatorColumnIsAllowed;
+ }
+
+ protected void setSpecifiedDiscriminatorColumnIsAllowed(boolean allowed) {
+ boolean old = this.specifiedDiscriminatorColumnIsAllowed;
+ this.specifiedDiscriminatorColumnIsAllowed = allowed;
+ this.firePropertyChanged(SPECIFIED_DISCRIMINATOR_COLUMN_IS_ALLOWED_PROPERTY, old, allowed);
+ }
+
+ protected boolean buildSpecifiedDiscriminatorColumnIsAllowed() {
+ return ! this.isTablePerClass() && this.isRoot();
+ }
+
+ public boolean discriminatorColumnIsUndefined() {
+ return this.discriminatorColumnIsUndefined;
+ }
+
+ protected void setDiscriminatorColumnIsUndefined(boolean undefined) {
+ boolean old = this.discriminatorColumnIsUndefined;
+ this.discriminatorColumnIsUndefined = undefined;
+ this.firePropertyChanged(DISCRIMINATOR_COLUMN_IS_UNDEFINED_PROPERTY, old, undefined);
+ }
+
+ protected boolean buildDiscriminatorColumnIsUndefined() {
+ return this.isTablePerClass() ||
+ this.isRootNoDescendantsNoStrategyDefined();
+ }
+
+
+ // ********** attribute override container **********
+
+ public JavaAttributeOverrideContainer getAttributeOverrideContainer() {
+ return this.attributeOverrideContainer;
+ }
+
+ protected JavaAttributeOverrideContainer buildAttributeOverrideContainer() {
+ return this.getJpaFactory().buildJavaAttributeOverrideContainer(this, new AttributeOverrideContainerOwner());
+ }
+
+ public TypeMapping getOverridableTypeMapping() {
+ PersistentType superPersistentType = this.getPersistentType().getSuperPersistentType();
+ return (superPersistentType == null) ? null : superPersistentType.getMapping();
+ }
+
+
+ // ********** association override container **********
+
+ public JavaAssociationOverrideContainer getAssociationOverrideContainer() {
+ return this.associationOverrideContainer;
+ }
+
+ protected JavaAssociationOverrideContainer buildAssociationOverrideContainer() {
+ return this.getJpaFactory().buildJavaAssociationOverrideContainer(this, new AssociationOverrideContainerOwner());
+ }
+
+ @Override
+ public Relationship resolveOverriddenRelationship(String attributeName) {
+ // check for an override before looking at attribute mappings
+ AssociationOverride override = this.associationOverrideContainer.getSpecifiedOverrideNamed(attributeName);
+ return (override != null) ? override.getRelationship() : super.resolveOverriddenRelationship(attributeName);
+ }
+
+
+ // ********** generator container **********
+
+ public JavaGeneratorContainer getGeneratorContainer() {
+ return this.generatorContainer;
+ }
+
+ protected JavaGeneratorContainer buildGeneratorContainer() {
+ return this.getJpaFactory().buildJavaGeneratorContainer(this, this);
+ }
+
+ public JavaResourcePersistentMember getResourceAnnotatedElement() {
+ return this.getResourcePersistentType();
+ }
+
+
+ // ********** query container **********
+
+ public JavaQueryContainer getQueryContainer() {
+ return this.queryContainer;
+ }
+
+ protected JavaQueryContainer buildQueryContainer() {
+ return this.getJpaFactory().buildJavaQueryContainer(this, this);
+ }
+
+
+ // ********** associated tables **********
+
+ @Override
+ public Iterator<ReadOnlyTable> associatedTables() {
+ return this.getAssociatedTables().iterator();
+ }
+
+ public Iterable<ReadOnlyTable> getAssociatedTables() {
+ return new CompositeIterable<ReadOnlyTable>(this.table, this.getSecondaryTables());
+ }
+
+ @Override
+ public Iterator<ReadOnlyTable> allAssociatedTables() {
+ return new CompositeIterator<ReadOnlyTable>(this.allAssociatedTablesLists());
+ }
+
+ public Iterable<ReadOnlyTable> getAllAssociatedTables() {
+ return CollectionTools.iterable(this.allAssociatedTables());
+ }
+
+ // TODO eliminate duplicate tables?
+ protected Iterator<Iterator<ReadOnlyTable>> allAssociatedTablesLists() {
+ return new TransformationIterator<TypeMapping, Iterator<ReadOnlyTable>>(this.inheritanceHierarchy(), TypeMappingTools.ASSOCIATED_TABLES_TRANSFORMER);
+ }
+
+ @Override
+ public Iterator<String> allAssociatedTableNames() {
+ return this.getAllAssociatedTableNames().iterator();
+ }
+
+ public Iterable<String> getAllAssociatedTableNames() {
+ return this.convertToNames(this.getAllAssociatedTables());
+ }
+
+ /**
+ * strip out <code>null</code> names
+ */
+ protected Iterable<String> convertToNames(Iterable<ReadOnlyTable> tables) {
+ return new FilteringIterable<String>(this.convertToNames_(tables), NotNullFilter.<String>instance());
+ }
+
+ protected Iterable<String> convertToNames_(Iterable<ReadOnlyTable> tables) {
+ return new TransformationIterable<ReadOnlyTable, String>(tables) {
+ @Override
+ protected String transform(ReadOnlyTable t) {
+ return t.getName();
+ }
+ };
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return ! this.tableNameIsValid(tableName);
+ }
+
+ protected boolean tableNameIsValid(String tableName) {
+ return this.tableIsUndefined || CollectionTools.contains(this.getAllAssociatedTableNames(), tableName);
+ }
+
+
+ // ********** database **********
+
+ @Override
+ public String getPrimaryTableName() {
+ return this.table.getName();
+ }
+
+ @Override
+ public org.eclipse.jpt.jpa.db.Table getPrimaryDbTable() {
+ return this.table.getDbTable();
+ }
+
+ @Override
+ public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) {
+ // matching database objects and identifiers is database platform-specific
+ return this.getDataSource().selectDatabaseObjectForIdentifier(this.getAllAssociatedDbTables(), tableName);
+ }
+
+ /**
+ * strip out null db tables
+ */
+ protected Iterable<org.eclipse.jpt.jpa.db.Table> getAllAssociatedDbTables() {
+ return new FilteringIterable<org.eclipse.jpt.jpa.db.Table>(this.getAllAssociatedDbTables_(), NotNullFilter.<org.eclipse.jpt.jpa.db.Table>instance());
+ }
+
+ protected Iterable<org.eclipse.jpt.jpa.db.Table> getAllAssociatedDbTables_() {
+ return new TransformationIterable<ReadOnlyTable, org.eclipse.jpt.jpa.db.Table>(this.getAllAssociatedTables()) {
+ @Override
+ protected org.eclipse.jpt.jpa.db.Table transform(ReadOnlyTable entityTable) {
+ return entityTable.getDbTable();
+ }
+ };
+ }
+
+ @Override
+ public Schema getDbSchema() {
+ return this.table.getDbSchema();
+ }
+
+
+ // ********** primary key **********
+
+ public String getPrimaryKeyColumnName() {
+ return MappingTools.getPrimaryKeyColumnName(this);
+ }
+
+ public PersistentAttribute getIdAttribute() {
+ Iterator<AttributeMapping> idAttributeMappings = this.getAllAttributeMappings(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY).iterator();
+ if (idAttributeMappings.hasNext()) {
+ PersistentAttribute attribute = idAttributeMappings.next().getPersistentAttribute();
+ return idAttributeMappings.hasNext() ? null /*more than one*/: attribute;
+ }
+ return null;
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.ENTITY_TYPE_MAPPING_KEY;
+ }
+
+ public boolean isMapped() {
+ return true;
+ }
+
+ @Override
+ public JavaResourcePersistentType getResourcePersistentType() {
+ return super.getResourcePersistentType();
+ }
+
+
+ // ********** attribute mappings **********
+
+ @Override
+ public Column resolveOverriddenColumn(String attributeName) {
+ // check for an override before looking at attribute mappings
+ AttributeOverride override = this.attributeOverrideContainer.getSpecifiedOverrideNamed(attributeName);
+ return (override != null) ? override.getColumn() : super.resolveOverriddenColumn(attributeName);
+ }
+
+ @Override
+ public Iterator<String> overridableAttributeNames() {
+ return this.isTablePerClass() ?
+ super.overridableAttributeNames() :
+ EmptyIterator.<String>instance();
+ }
+
+ @Override
+ public Iterator<String> overridableAssociationNames() {
+ return this.isTablePerClass() ?
+ super.overridableAssociationNames() :
+ EmptyIterator.<String>instance();
+ }
+
+ public AttributeMapping resolveAttributeMapping(String name) {
+ for (AttributeMapping attributeMapping : CollectionTools.iterable(this.allAttributeMappings())) {
+ AttributeMapping resolvedMapping = attributeMapping.resolveAttributeMapping(name);
+ if (resolvedMapping != null) {
+ return resolvedMapping;
+ }
+ }
+ return null;
+ }
+
+
+ // ********** inheritance **********
+
+ public Entity getParentEntity() {
+ for (TypeMapping typeMapping : this.getAncestors()) {
+ if (typeMapping instanceof Entity) {
+ return (Entity) typeMapping;
+ }
+ }
+ return null;
+ }
+
+ public boolean isRoot() {
+ return this == this.rootEntity;
+ }
+
+ /**
+ * Return whether the entity is a descendant in (as opposed to the root of)
+ * an inheritance hierarchy.
+ */
+ protected boolean isDescendant() {
+ return ! this.isRoot();
+ }
+
+ /**
+ * Return whether the entity is a descendant of the root entity
+ * of a "single table" inheritance hierarchy.
+ */
+ protected boolean isSingleTableDescendant() {
+ return this.isDescendant() &&
+ (this.getInheritanceStrategy() == InheritanceType.SINGLE_TABLE);
+ }
+
+ /**
+ * Return whether the entity is the top of an inheritance hierarchy
+ * and has no descendants and no specified inheritance strategy has been defined.
+ */
+ protected boolean isRootNoDescendantsNoStrategyDefined() {
+ return this.isRoot() &&
+ this.descendants.isEmpty() &&
+ (this.specifiedInheritanceStrategy == null);
+ }
+
+ /**
+ * Return whether the entity is abstract and is a part of a
+ * "table per class" inheritance hierarchy.
+ */
+ protected boolean isAbstractTablePerClass() {
+ return this.isAbstract() && this.isTablePerClass();
+ }
+
+ /**
+ * Return whether the entity is a part of a "table per class"
+ * inheritance hierarchy.
+ */
+ protected boolean isTablePerClass() {
+ return this.getInheritanceStrategy() == InheritanceType.TABLE_PER_CLASS;
+ }
+
+ /**
+ * Return whether the entity is a part of a "table per class"
+ * inheritance hierarchy.
+ */
+ protected boolean isTablePerClassDescendant() {
+ return this.isTablePerClass() && this.isDescendant();
+ }
+
+ /**
+ * Return whether the type is abstract.
+ */
+ protected boolean isAbstract() {
+ return this.getResourcePersistentType().isAbstract();
+ }
+
+ /**
+ * Return whether the entity's type is final.
+ */
+ protected boolean isFinal() {
+ return this.getResourcePersistentType().isFinal();
+ }
+
+ /**
+ * Return whether the entity's type is a member of another type.
+ */
+ protected boolean isMember() {
+ return this.getResourcePersistentType().isMemberType();
+ }
+
+ /**
+ * Return whether the entity's type is static.
+ */
+ protected boolean isStatic() {
+ return this.getResourcePersistentType().isStatic();
+ }
+
+
+ // ********** 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.table.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ for (JavaSecondaryTable secondaryTable : CollectionTools.iterable(this.secondaryTables())) {
+ result = secondaryTable.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ }
+ for (JavaPrimaryKeyJoinColumn pkJoinColumn : CollectionTools.iterable(this.primaryKeyJoinColumns())) {
+ result = pkJoinColumn.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ }
+ result = this.attributeOverrideContainer.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ result = this.associationOverrideContainer.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ result = this.discriminatorColumn.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ result = this.generatorContainer.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.validatePrimaryKey(messages, reporter, astRoot);
+ this.validateTable(messages, reporter, astRoot);
+ for (JavaSecondaryTable secondaryTable : this.getSecondaryTables()) {
+ secondaryTable.validate(messages, reporter, astRoot);
+ }
+ this.validateInheritance(messages, reporter, astRoot);
+ for (JavaPrimaryKeyJoinColumn pkJoinColumn : this.getPrimaryKeyJoinColumns()) {
+ pkJoinColumn.validate(messages, reporter, astRoot);
+ }
+ this.generatorContainer.validate(messages, reporter, astRoot);
+ this.queryContainer.validate(messages, reporter, astRoot);
+ this.attributeOverrideContainer.validate(messages, reporter, astRoot);
+ this.associationOverrideContainer.validate(messages, reporter, astRoot);
+ this.validateEntityName(messages, reporter, astRoot);
+ this.validateDuplicateEntityNames(messages, reporter, astRoot);
+ }
+
+ @Override
+ public boolean validatesAgainstDatabase() {
+ return super.validatesAgainstDatabase() && ! this.isAbstractTablePerClass();
+ }
+
+ protected void validateEntityName(List<IMessage> messages,
+ IReporter reporter, CompilationUnit astRoot) {
+ if (StringTools.stringIsEmpty(this.getName())){
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_NAME_MISSING,
+ new String[] {this.getPersistentType().getName()},
+ this,
+ this.getMappingAnnotation().getNameTextRange(astRoot)
+ )
+ );
+ }
+ }
+
+ protected void validateDuplicateEntityNames(List<IMessage> messages,
+ IReporter reporter, CompilationUnit astRoot) {
+ HashBag<String> javaEntityNamesExclOverridden = new HashBag<String>();
+ CollectionTools.addAll(javaEntityNamesExclOverridden, this.getPersistenceUnit().javaEntityNamesExclOverridden());
+ HashBag<String> ormEntityNames = new HashBag<String>();
+ CollectionTools.addAll(ormEntityNames, this.getPersistenceUnit().ormEntityNames());
+ String javaEntityName = this.getName();
+ if ((javaEntityName != null)
+ // Check whether or not this entity name has duplicates among
+ // the java entities that are not overridden by orm entities
+ && ((javaEntityNamesExclOverridden.count(javaEntityName) > 1)
+ //Check whether or not this entity name has duplicates
+ //with the names of orm entities
+ || (ormEntityNames.contains(javaEntityName)))) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.PERSISTENCE_UNIT_ENTITY_NAME_ATTRIBUTE_MISSING,
+ new String[] {javaEntityName},
+ this,
+ this.getMappingAnnotation().getNameTextRange(astRoot)
+ )
+ );
+ }
+ }
+
+ protected void validatePrimaryKey(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.buildPrimaryKeyValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildPrimaryKeyValidator(CompilationUnit astRoot) {
+ return new GenericEntityPrimaryKeyValidator(this, this.buildTextRangeResolver(astRoot));
+ }
+
+ @Override
+ protected EntityTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaEntityTextRangeResolver(this, astRoot);
+ }
+
+ protected void validateTable(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ if (this.isAbstractTablePerClass()) {
+ if (this.table.isSpecifiedInResource()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_ABSTRACT_TABLE_PER_CLASS_DEFINES_TABLE,
+ new String[] {this.getName()},
+ this,
+ this.table.getValidationTextRange(astRoot)
+ )
+ );
+ }
+ return;
+ }
+ if (this.isSingleTableDescendant()) {
+ if (this.table.isSpecifiedInResource()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_SINGLE_TABLE_DESCENDANT_DEFINES_TABLE,
+ new String[] {this.getName()},
+ this,
+ this.table.getValidationTextRange(astRoot)
+ )
+ );
+ }
+ return;
+ }
+ this.table.validate(messages, reporter, astRoot);
+ }
+
+ protected void validateInheritance(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.validateInheritanceStrategy(messages, astRoot);
+ this.validateDiscriminatorColumn(messages, reporter, astRoot);
+ this.validateDiscriminatorValue(messages, astRoot);
+ }
+
+ protected void validateDiscriminatorColumn(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ if (this.specifiedDiscriminatorColumnIsAllowed && ! this.discriminatorColumnIsUndefined) {
+ this.discriminatorColumn.validate(messages, reporter, astRoot);
+ }
+ else if (this.discriminatorColumn.isResourceSpecified()) {
+ if (this.isDescendant()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_NON_ROOT_DISCRIMINATOR_COLUMN_DEFINED,
+ new String[] {this.getName()},
+ this,
+ this.getDiscriminatorColumnTextRange(astRoot)
+ )
+ );
+ }
+ else if (this.isTablePerClass()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_TABLE_PER_CLASS_DISCRIMINATOR_COLUMN_DEFINED,
+ new String[] {this.getName()},
+ this,
+ this.getDiscriminatorColumnTextRange(astRoot)
+ )
+ );
+ }
+ }
+ }
+
+ protected void validateDiscriminatorValue(List<IMessage> messages, CompilationUnit astRoot) {
+ if (this.discriminatorValueIsUndefined && (this.specifiedDiscriminatorValue != null)) {
+ if (this.isAbstract()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.NORMAL_SEVERITY,
+ JpaValidationMessages.ENTITY_ABSTRACT_DISCRIMINATOR_VALUE_DEFINED,
+ new String[] {this.getName()},
+ this,
+ this.getDiscriminatorValueTextRange(astRoot)
+ )
+ );
+ }
+ else if (this.isTablePerClass()) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.NORMAL_SEVERITY,
+ JpaValidationMessages.ENTITY_TABLE_PER_CLASS_DISCRIMINATOR_VALUE_DEFINED,
+ new String[] {this.getName()},
+ this,
+ this.getDiscriminatorValueTextRange(astRoot)
+ )
+ );
+ }
+ }
+ }
+
+ protected void validateInheritanceStrategy(List<IMessage> messages, CompilationUnit astRoot) {
+ Supported tablePerConcreteClassInheritanceIsSupported = this.getJpaPlatformVariation().getTablePerConcreteClassInheritanceIsSupported();
+ if (tablePerConcreteClassInheritanceIsSupported == Supported.YES) {
+ return;
+ }
+ if ((this.getInheritanceStrategy() == InheritanceType.TABLE_PER_CLASS) && this.isRoot()) {
+ if (tablePerConcreteClassInheritanceIsSupported == Supported.NO) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.ENTITY_TABLE_PER_CLASS_NOT_SUPPORTED_ON_PLATFORM,
+ new String[] {this.getName()},
+ this,
+ this.getInheritanceStrategyTextRange(astRoot)
+ )
+ );
+ }
+ else {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.NORMAL_SEVERITY,
+ JpaValidationMessages.ENTITY_TABLE_PER_CLASS_NOT_PORTABLE_ON_PLATFORM,
+ new String[] {this.getName()},
+ this,
+ this.getInheritanceStrategyTextRange(astRoot)
+ )
+ );
+ }
+ }
+ }
+
+ protected TextRange getDiscriminatorValueTextRange(CompilationUnit astRoot) {
+ return this.getDiscriminatorValueAnnotation().getTextRange(astRoot);
+ }
+
+ protected TextRange getDiscriminatorColumnTextRange(CompilationUnit astRoot) {
+ return this.discriminatorColumn.getValidationTextRange(astRoot);
+ }
+
+ protected TextRange getInheritanceStrategyTextRange(CompilationUnit astRoot) {
+ return this.getInheritanceAnnotation().getStrategyTextRange(astRoot);
+ }
+
+
+ // ********** OrmOverrideContainer.Owner implementation **********
+
+ /**
+ * some common behavior
+ */
+ protected abstract class OverrideContainerOwner
+ implements JavaOverrideContainer.Owner
+ {
+ public JavaResourcePersistentMember getResourcePersistentMember() {
+ return AbstractJavaEntity.this.getResourcePersistentType();
+ }
+
+ public JavaTypeMapping getTypeMapping() {
+ return AbstractJavaEntity.this;
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return AbstractJavaEntity.this.getValidationTextRange(astRoot);
+ }
+
+ public TypeMapping getOverridableTypeMapping() {
+ return AbstractJavaEntity.this.getOverridableTypeMapping();
+ }
+
+ public Iterator<String> allOverridableNames() {
+ TypeMapping typeMapping = this.getOverridableTypeMapping();
+ return (typeMapping != null) ? this.allOverridableNames_(typeMapping) : EmptyIterator.<String>instance();
+ }
+
+ /**
+ * pre-condition: <code>typeMapping</code> is not <code>null</code>
+ */
+ protected abstract Iterator<String> allOverridableNames_(TypeMapping typeMapping);
+
+ public String getDefaultTableName() {
+ return AbstractJavaEntity.this.getPrimaryTableName();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return AbstractJavaEntity.this.tableNameIsInvalid(tableName);
+ }
+
+ public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) {
+ return AbstractJavaEntity.this.resolveDbTable(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return AbstractJavaEntity.this.allAssociatedTableNames();
+ }
+
+ public String getPossiblePrefix() {
+ return null;
+ }
+
+ public String getWritePrefix() {
+ return null;
+ }
+
+ // no maps, so all overrides are relevant
+ public boolean isRelevant(String overrideName) {
+ return true;
+ }
+
+ }
+
+
+ // ********** JavaAttributeOverrideContainer.Owner implementation **********
+
+ protected class AttributeOverrideContainerOwner
+ extends OverrideContainerOwner
+ implements JavaAttributeOverrideContainer.Owner
+ {
+ @Override
+ protected Iterator<String> allOverridableNames_(TypeMapping typeMapping) {
+ final Collection<String> mappedByRelationshipAttributes = CollectionTools.collection(
+ new TransformationIterator<SingleRelationshipMapping2_0, String>(this.getMapsIdRelationships()) {
+ @Override
+ protected String transform(SingleRelationshipMapping2_0 mapping) {
+ return mapping.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getValue();
+ }
+ });
+ return new FilteringIterator<String>(typeMapping.allOverridableAttributeNames()) {
+ @Override
+ protected boolean accept(String name) {
+ if (mappedByRelationshipAttributes.isEmpty()) {
+ return true;
+ }
+ // overridable names are (usually?) qualified with a container mapping,
+ // which may also be the one mapped by a relationship
+ int index = name.indexOf('.');
+ String qualifier = (index > 0) ? name.substring(0, index) : name;
+ return ! mappedByRelationshipAttributes.contains(qualifier);
+ }
+ };
+ }
+
+ protected Iterable<SingleRelationshipMapping2_0> getMapsIdRelationships() {
+ return new FilteringIterable<SingleRelationshipMapping2_0>(this.getSingleRelationshipMappings()) {
+ @Override
+ protected boolean accept(SingleRelationshipMapping2_0 mapping) {
+ return mapping.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy();
+ }
+ };
+ }
+
+ protected Iterable<SingleRelationshipMapping2_0> getSingleRelationshipMappings() {
+ return new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>(this.getSingleRelationshipMappings_());
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Iterable<AttributeMapping> getSingleRelationshipMappings_() {
+ return new CompositeIterable<AttributeMapping>(
+ this.getTypeMapping().getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY),
+ this.getTypeMapping().getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY)
+ );
+ }
+ public Column resolveOverriddenColumn(String attributeName) {
+ return MappingTools.resolveOverriddenColumn(this.getOverridableTypeMapping(), attributeName);
+ }
+
+ public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) {
+ return new AttributeOverrideValidator((AttributeOverride) override, (AttributeOverrideContainer) container, textRangeResolver, new MappedSuperclassOverrideDescriptionProvider());
+ }
+
+ public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner owner, BaseColumnTextRangeResolver textRangeResolver) {
+ return new AttributeOverrideColumnValidator((AttributeOverride) override, column, textRangeResolver, new EntityTableDescriptionProvider());
+ }
+ }
+
+
+ // ********** JavaAssociationOverrideContainer.Owner implementation **********
+
+ protected class AssociationOverrideContainerOwner
+ extends OverrideContainerOwner
+ implements JavaAssociationOverrideContainer.Owner
+ {
+ @Override
+ protected Iterator<String> allOverridableNames_(TypeMapping typeMapping) {
+ return typeMapping.allOverridableAssociationNames();
+ }
+
+ public Relationship resolveOverriddenRelationship(String attributeName) {
+ return MappingTools.resolveOverriddenRelationship(this.getOverridableTypeMapping(), attributeName);
+ }
+
+ public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) {
+ return new AssociationOverrideValidator((AssociationOverride) override, (AssociationOverrideContainer) container, textRangeResolver, new MappedSuperclassOverrideDescriptionProvider());
+ }
+
+ public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner owner, BaseColumnTextRangeResolver textRangeResolver) {
+ return new AssociationOverrideJoinColumnValidator((AssociationOverride) override, (JoinColumn) column, (JoinColumn.Owner) owner, (JoinColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider());
+ }
+
+ public JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
+ return new AssociationOverrideJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
+ }
+
+ public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) {
+ return new AssociationOverrideInverseJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider());
+ }
+
+ public JptValidator buildTableValidator(AssociationOverride override, Table t, TableTextRangeResolver textRangeResolver) {
+ return new AssociationOverrideJoinTableValidator(override, (JoinTable) t, textRangeResolver);
+ }
+ }
+
+
+ // ********** JavaNamedColumn.Owner implementation **********
+
+ /**
+ * some common behavior
+ */
+ protected abstract class NamedColumnOwner
+ implements JavaNamedColumn.Owner
+ {
+ public TypeMapping getTypeMapping() {
+ return AbstractJavaEntity.this;
+ }
+
+ public String getDefaultTableName() {
+ return AbstractJavaEntity.this.getPrimaryTableName();
+ }
+
+ public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) {
+ return AbstractJavaEntity.this.resolveDbTable(tableName);
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return AbstractJavaEntity.this.getValidationTextRange(astRoot);
+ }
+ }
+
+
+ // ********** JavaBaseJoinColumn.Owner implementation **********
+
+ protected class PrimaryKeyJoinColumnOwner
+ extends NamedColumnOwner
+ implements JavaBaseJoinColumn.Owner
+ {
+ public org.eclipse.jpt.jpa.db.Table getReferencedColumnDbTable() {
+ Entity parentEntity = AbstractJavaEntity.this.getParentEntity();
+ return (parentEntity == null) ? null : parentEntity.getPrimaryDbTable();
+ }
+
+ public int joinColumnsSize() {
+ return AbstractJavaEntity.this.primaryKeyJoinColumnsSize();
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return AbstractJavaEntity.this.defaultPrimaryKeyJoinColumn == joinColumn;
+ }
+
+ public String getDefaultColumnName() {
+ if (this.joinColumnsSize() != 1) {
+ return null;
+ }
+ Entity parentEntity = AbstractJavaEntity.this.getParentEntity();
+ return (parentEntity == null) ? AbstractJavaEntity.this.getPrimaryKeyColumnName() : parentEntity.getPrimaryKeyColumnName();
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new EntityPrimaryKeyJoinColumnValidator((BaseJoinColumn) column, this, (BaseJoinColumnTextRangeResolver) textRangeResolver);
+ }
+ }
+
+
+ // ********** JavaDiscriminatorColumn.Owner implementation **********
+
+ protected class DiscriminatorColumnOwner
+ extends NamedColumnOwner
+ implements JavaDiscriminatorColumn.Owner
+ {
+ public String getDefaultColumnName() {
+ return this.isDescendant() ?
+ this.getRootDiscriminatorColumn().getName() :
+ this.discriminatorColumnIsUndefined() ? null : DiscriminatorColumn.DEFAULT_NAME;
+ }
+
+ public int getDefaultLength() {
+ return this.isDescendant() ?
+ this.getRootDiscriminatorColumn().getLength() :
+ this.discriminatorColumnIsUndefined() ? 0 : DiscriminatorColumn.DEFAULT_LENGTH;
+ }
+
+ public DiscriminatorType getDefaultDiscriminatorType() {
+ return this.isDescendant() ?
+ this.getRootDiscriminatorColumn().getDiscriminatorType() :
+ this.discriminatorColumnIsUndefined() ? null : DiscriminatorColumn.DEFAULT_DISCRIMINATOR_TYPE;
+ }
+
+ protected boolean isDescendant() {
+ return AbstractJavaEntity.this.isDescendant();
+ }
+
+ protected DiscriminatorColumn getRootDiscriminatorColumn() {
+ return AbstractJavaEntity.this.rootEntity.getDiscriminatorColumn();
+ }
+
+ protected boolean discriminatorColumnIsUndefined() {
+ return AbstractJavaEntity.this.discriminatorColumnIsUndefined;
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new DiscriminatorColumnValidator(column, textRangeResolver);
+ }
+ }
+
+
+ // ********** table owner **********
+
+ protected class TableOwner implements Table.Owner {
+ public JptValidator buildTableValidator(Table t, TableTextRangeResolver textRangeResolver) {
+ return new TableValidator(t, textRangeResolver);
+ }
+ }
+
+
+ // ********** secondary table owner **********
+
+ protected class SecondaryTableOwner implements Table.Owner {
+ public JptValidator buildTableValidator(Table t, TableTextRangeResolver textRangeResolver) {
+ return new SecondaryTableValidator((SecondaryTable) t, textRangeResolver);
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaGenerator.java
new file mode 100644
index 0000000000..cc79849d49
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaGenerator.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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.Generator;
+import org.eclipse.jpt.jpa.core.context.java.JavaGenerator;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.resource.java.GeneratorAnnotation;
+import org.eclipse.jpt.jpa.db.Catalog;
+import org.eclipse.jpt.jpa.db.Schema;
+import org.eclipse.jpt.jpa.db.SchemaContainer;
+
+/**
+ * Java sequence or table generator
+ */
+public abstract class AbstractJavaGenerator<A extends GeneratorAnnotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaGenerator
+{
+ protected final A generatorAnnotation;
+
+ protected String name;
+
+ protected Integer specifiedInitialValue;
+ protected int defaultInitialValue;
+
+ protected Integer specifiedAllocationSize;
+ protected int defaultAllocationSize;
+
+
+ protected AbstractJavaGenerator(JavaJpaContextNode parent, A generatorAnnotation) {
+ super(parent);
+ this.generatorAnnotation = generatorAnnotation;
+ this.name = generatorAnnotation.getName();
+ this.specifiedInitialValue = generatorAnnotation.getInitialValue();
+ this.specifiedAllocationSize = generatorAnnotation.getAllocationSize();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setName_(this.generatorAnnotation.getName());
+ this.setSpecifiedInitialValue_(this.generatorAnnotation.getInitialValue());
+ this.setSpecifiedAllocationSize_(this.generatorAnnotation.getAllocationSize());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultInitialValue(this.buildDefaultInitialValue());
+ this.setDefaultAllocationSize(this.buildDefaultAllocationSize());
+ this.getPersistenceUnit().addGenerator(this);
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.generatorAnnotation.setName(name);
+ this.setName_(name);
+ }
+
+ protected void setName_(String name) {
+ String old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ // ********** initial value **********
+
+ public int getInitialValue() {
+ return (this.specifiedInitialValue != null) ? this.specifiedInitialValue.intValue() : this.defaultInitialValue;
+ }
+
+ public Integer getSpecifiedInitialValue() {
+ return this.specifiedInitialValue;
+ }
+
+ public void setSpecifiedInitialValue(Integer value) {
+ this.generatorAnnotation.setInitialValue(value);
+ this.setSpecifiedInitialValue_(value);
+ }
+
+ protected void setSpecifiedInitialValue_(Integer value) {
+ Integer old = this.specifiedInitialValue;
+ this.specifiedInitialValue = value;
+ this.firePropertyChanged(SPECIFIED_INITIAL_VALUE_PROPERTY, old, value);
+ }
+
+ public int getDefaultInitialValue() {
+ return this.defaultInitialValue;
+ }
+
+ protected void setDefaultInitialValue(int value) {
+ int old = this.defaultInitialValue;
+ this.defaultInitialValue = value;
+ this.firePropertyChanged(DEFAULT_INITIAL_VALUE_PROPERTY, old, value);
+ }
+
+ protected abstract int buildDefaultInitialValue();
+
+
+ // ********** allocation size **********
+
+ public int getAllocationSize() {
+ return (this.specifiedAllocationSize != null) ? this.specifiedAllocationSize.intValue() : this.defaultAllocationSize;
+ }
+
+ public Integer getSpecifiedAllocationSize() {
+ return this.specifiedAllocationSize;
+ }
+
+ public void setSpecifiedAllocationSize(Integer size) {
+ this.generatorAnnotation.setAllocationSize(size);
+ this.setSpecifiedAllocationSize_(size);
+ }
+
+ protected void setSpecifiedAllocationSize_(Integer size) {
+ Integer old = this.specifiedAllocationSize;
+ this.specifiedAllocationSize = size;
+ this.firePropertyChanged(SPECIFIED_ALLOCATION_SIZE_PROPERTY, old, size);
+ }
+
+ public int getDefaultAllocationSize() {
+ return this.defaultAllocationSize;
+ }
+
+ protected void setDefaultAllocationSize(int size) {
+ int old = this.defaultAllocationSize;
+ this.defaultAllocationSize = size;
+ this.firePropertyChanged(DEFAULT_ALLOCATION_SIZE_PROPERTY, old, size);
+ }
+
+ protected int buildDefaultAllocationSize() {
+ return DEFAULT_ALLOCATION_SIZE;
+ }
+
+
+ // ********** text ranges **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getSelectionTextRange(astRoot);
+ }
+
+ public TextRange getSelectionTextRange(CompilationUnit astRoot) {
+ return this.generatorAnnotation.getTextRange(astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return this.generatorAnnotation.getNameTextRange(astRoot);
+ }
+
+
+ // ********** database stuff **********
+
+ public Schema getDbSchema() {
+ SchemaContainer dbSchemaContainer = this.getDbSchemaContainer();
+ return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema());
+ }
+
+ /**
+ * 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.resolveDbCatalog(catalog) : this.getDatabase();
+ }
+
+ protected abstract String getSchema();
+
+ /**
+ * 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.resolveDbCatalog(catalog);
+ }
+
+ protected abstract String getCatalog();
+
+
+ // ********** JpaNamedContextNode implementation **********
+
+ public boolean overrides(Generator other) {
+ return MappingTools.nodeOverrides(this, other, PRECEDENCE_TYPE_LIST);
+ }
+
+ public boolean duplicates(Generator other) {
+ return MappingTools.nodesAreDuplicates(this, other);
+ }
+
+
+ // ********** misc **********
+
+ public A getGeneratorAnnotation() {
+ return this.generatorAnnotation;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.name);
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMapping.java
new file mode 100644
index 0000000000..ac83d194a1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMapping.java
@@ -0,0 +1,476 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
+import org.eclipse.jpt.common.utility.internal.Association;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.SimpleAssociation;
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Converter;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaGeneratedValue;
+import org.eclipse.jpt.jpa.core.context.java.JavaGeneratorContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaIdMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaTemporalConverter;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.NamedColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaConverter;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.jpa2.context.IdMapping2_0;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.GeneratedValueAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.IdAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java ID mapping
+ */
+public abstract class AbstractJavaIdMapping
+ extends AbstractJavaAttributeMapping<IdAnnotation>
+ implements JavaIdMapping, IdMapping2_0
+{
+ protected final JavaColumn column;
+
+ protected final JavaGeneratorContainer generatorContainer;
+
+ protected JavaGeneratedValue generatedValue;
+
+ protected JavaConverter converter; // never null
+
+ /* 2.0 feature - a relationship may map this id */
+ protected boolean mappedByRelationship;
+
+
+ protected static final JavaConverter.Adapter[] CONVERTER_ADAPTER_ARRAY = new JavaConverter.Adapter[] {
+ JavaTemporalConverter.Adapter.instance(),
+ };
+ protected static final Iterable<JavaConverter.Adapter> CONVERTER_ADAPTERS = new ArrayIterable<JavaConverter.Adapter>(CONVERTER_ADAPTER_ARRAY);
+
+
+ protected AbstractJavaIdMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.column = this.buildColumn();
+ this.generatorContainer = this.buildGeneratorContainer();
+ this.generatedValue = this.buildGeneratedValue();
+ this.converter = this.buildConverter();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.column.synchronizeWithResourceModel();
+ this.generatorContainer.synchronizeWithResourceModel();
+ this.syncGeneratedValue();
+ this.syncConverter();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.column.update();
+ this.generatorContainer.update();
+ if (this.generatedValue != null) {
+ this.generatedValue.update();
+ }
+ this.converter.update();
+ this.setMappedByRelationship(this.buildMappedByRelationship());
+ }
+
+
+ // ********** column **********
+
+ public JavaColumn getColumn() {
+ return this.column;
+ }
+
+ protected JavaColumn buildColumn() {
+ return this.getJpaFactory().buildJavaColumn(this, this);
+ }
+
+
+ // ********** generator container **********
+
+ public JavaGeneratorContainer getGeneratorContainer() {
+ return this.generatorContainer;
+ }
+
+ private JavaGeneratorContainer buildGeneratorContainer() {
+ return this.getJpaFactory().buildJavaGeneratorContainer(this, this);
+ }
+
+
+ // ********** generated value **********
+
+ public JavaGeneratedValue getGeneratedValue() {
+ return this.generatedValue;
+ }
+
+ public JavaGeneratedValue addGeneratedValue() {
+ if (this.generatedValue != null) {
+ throw new IllegalStateException("generated value already exists: " + this.generatedValue); //$NON-NLS-1$
+ }
+ GeneratedValueAnnotation annotation = this.buildGeneratedValueAnnotation();
+ JavaGeneratedValue value = this.buildGeneratedValue(annotation);
+ this.setGeneratedValue(value);
+ return value;
+ }
+
+ protected GeneratedValueAnnotation buildGeneratedValueAnnotation() {
+ return (GeneratedValueAnnotation) this.getResourcePersistentAttribute().addAnnotation(GeneratedValueAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeGeneratedValue() {
+ if (this.generatedValue == null) {
+ throw new IllegalStateException("generated value does not exist"); //$NON-NLS-1$
+ }
+ this.getResourcePersistentAttribute().removeAnnotation(GeneratedValueAnnotation.ANNOTATION_NAME);
+ this.setGeneratedValue(null);
+ }
+
+ protected JavaGeneratedValue buildGeneratedValue() {
+ GeneratedValueAnnotation annotation = this.getGeneratedValueAnnotation();
+ return (annotation == null) ? null : this.buildGeneratedValue(annotation);
+ }
+
+ protected GeneratedValueAnnotation getGeneratedValueAnnotation() {
+ return (GeneratedValueAnnotation) this.getResourcePersistentAttribute().getAnnotation(GeneratedValueAnnotation.ANNOTATION_NAME);
+ }
+
+ protected JavaGeneratedValue buildGeneratedValue(GeneratedValueAnnotation generatedValueAnnotation) {
+ return this.getJpaFactory().buildJavaGeneratedValue(this, generatedValueAnnotation);
+ }
+
+ protected void syncGeneratedValue() {
+ GeneratedValueAnnotation annotation = this.getGeneratedValueAnnotation();
+ if (annotation == null) {
+ if (this.generatedValue != null) {
+ this.setGeneratedValue(null);
+ }
+ }
+ else {
+ if ((this.generatedValue != null) && (this.generatedValue.getGeneratedValueAnnotation() == annotation)) {
+ this.generatedValue.synchronizeWithResourceModel();
+ } else {
+ this.setGeneratedValue(this.buildGeneratedValue(annotation));
+ }
+ }
+ }
+
+ protected void setGeneratedValue(JavaGeneratedValue value) {
+ JavaGeneratedValue old = this.generatedValue;
+ this.generatedValue = value;
+ this.firePropertyChanged(GENERATED_VALUE_PROPERTY, old, value);
+ }
+
+
+ // ********** converter **********
+
+ public JavaConverter getConverter() {
+ return this.converter;
+ }
+
+ public void setConverter(Class<? extends Converter> converterType) {
+ if (this.converter.getType() != converterType) {
+ this.converter.dispose();
+ JavaConverter.Adapter converterAdapter = this.getConverterAdapter(converterType);
+ this.retainConverterAnnotation(converterAdapter);
+ this.setConverter_(this.buildConverter(converterAdapter));
+ }
+ }
+
+ protected JavaConverter buildConverter(JavaConverter.Adapter converterAdapter) {
+ return (converterAdapter != null) ?
+ converterAdapter.buildNewConverter(this, this.getJpaFactory()) :
+ this.buildNullConverter();
+ }
+
+ protected void setConverter_(JavaConverter converter) {
+ Converter old = this.converter;
+ this.converter = converter;
+ this.firePropertyChanged(CONVERTER_PROPERTY, old, converter);
+ }
+
+ /**
+ * Clear all the converter annotations <em>except</em> for the annotation
+ * corresponding to the specified adapter. If the specified adapter is
+ * <code>null</code>, remove <em>all</em> the converter annotations.
+ */
+ protected void retainConverterAnnotation(JavaConverter.Adapter converterAdapter) {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter != converterAdapter) {
+ adapter.removeConverterAnnotation(resourceAttribute);
+ }
+ }
+ }
+
+ protected JavaConverter buildConverter() {
+ JpaFactory jpaFactory = this.getJpaFactory();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ JavaConverter javaConverter = adapter.buildConverter(this, jpaFactory);
+ if (javaConverter != null) {
+ return javaConverter;
+ }
+ }
+ return this.buildNullConverter();
+ }
+
+ protected void syncConverter() {
+ Association<JavaConverter.Adapter, Annotation> assoc = this.getConverterAnnotation();
+ if (assoc == null) {
+ if (this.converter.getType() != null) {
+ this.setConverter_(this.buildNullConverter());
+ }
+ } else {
+ JavaConverter.Adapter adapter = assoc.getKey();
+ Annotation annotation = assoc.getValue();
+ if ((this.converter.getType() == adapter.getConverterType()) &&
+ (this.converter.getConverterAnnotation() == annotation)) {
+ this.converter.synchronizeWithResourceModel();
+ } else {
+ this.setConverter_(adapter.buildConverter(annotation, this, this.getJpaFactory()));
+ }
+ }
+ }
+
+ /**
+ * Return the first converter annotation we find along with its corresponding
+ * adapter. Return <code>null</code> if there are no converter annotations.
+ */
+ protected Association<JavaConverter.Adapter, Annotation> getConverterAnnotation() {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ Annotation annotation = adapter.getConverterAnnotation(resourceAttribute);
+ if (annotation != null) {
+ return new SimpleAssociation<JavaConverter.Adapter, Annotation>(adapter, annotation);
+ }
+ }
+ return null;
+ }
+
+ protected JavaConverter buildNullConverter() {
+ return new NullJavaConverter(this);
+ }
+
+
+ // ********** converter adapters **********
+
+ /**
+ * Return the converter adapter for the specified converter type.
+ */
+ protected JavaConverter.Adapter getConverterAdapter(Class<? extends Converter> converterType) {
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter.getConverterType() == converterType) {
+ return adapter;
+ }
+ }
+ return null;
+ }
+
+ protected Iterable<JavaConverter.Adapter> getConverterAdapters() {
+ return CONVERTER_ADAPTERS;
+ }
+
+
+ // ********** mapped by relationship **********
+
+ public boolean isMappedByRelationship() {
+ return this.mappedByRelationship;
+ }
+
+ protected void setMappedByRelationship(boolean mappedByRelationship) {
+ boolean old = this.mappedByRelationship;
+ this.mappedByRelationship = mappedByRelationship;
+ this.firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, old, mappedByRelationship);
+ }
+
+ protected boolean buildMappedByRelationship() {
+ return this.isJpa2_0Compatible() && this.buildMappedByRelationship_();
+ }
+
+ protected boolean buildMappedByRelationship_() {
+ return CollectionTools.contains(this.getMappedByRelationshipAttributeNames(), this.getName());
+ }
+
+ protected Iterable<String> getMappedByRelationshipAttributeNames() {
+ return TypeMappingTools.getMappedByRelationshipAttributeNames(this.getTypeMapping());
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.ID_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return IdAnnotation.ANNOTATION_NAME;
+ }
+
+ @Override
+ public String getPrimaryKeyColumnName() {
+ return this.column.getName();
+ }
+
+ protected boolean columnIsSpecified() {
+ return this.getResourcePersistentAttribute().getAnnotation(ColumnAnnotation.ANNOTATION_NAME) != null;
+ }
+
+ @Override
+ public boolean isOverridableAttributeMapping() {
+ return true;
+ }
+
+
+ // ********** JavaGeneratorContainer implementation **********
+
+ public JavaResourcePersistentMember getResourceAnnotatedElement() {
+ return this.getResourcePersistentAttribute();
+ }
+
+
+ // ********** JavaColumn.Owner implementation **********
+
+ public ColumnAnnotation getColumnAnnotation() {
+ return (ColumnAnnotation) this.getResourcePersistentAttribute().getNonNullAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeColumnAnnotation() {
+ this.getResourcePersistentAttribute().removeAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public String getDefaultColumnName() {
+ return (this.mappedByRelationship && ! this.columnIsSpecified()) ? null : this.getName();
+ }
+
+ public String getDefaultTableName() {
+ return (this.mappedByRelationship && ! this.columnIsSpecified()) ? null : this.getTypeMapping().getPrimaryTableName();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return this.getTypeMapping().allAssociatedTableNames();
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new NamedColumnValidator((BaseColumn) column, (BaseColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider());
+ }
+
+
+ // ********** 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.column.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ result = this.generatorContainer.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ if (this.generatedValue != null) {
+ result = this.generatedValue.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ result = this.converter.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 id is not mapped by a relationship,
+ // then the column is validated.
+ // (In JPA 1.0, the column will always be validated, since the id is never mapped by a
+ // relationship)
+ if (this.columnIsSpecified() || ! this.mappedByRelationship) {
+ this.column.validate(messages, reporter, astRoot);
+ }
+
+ // [JPA 2.0] if the column is specified and the id is mapped by a relationship,
+ // then that is an error
+ // (In JPA 1.0, this will never be the case, since the id is never mapped by a relationship)
+ if (this.columnIsSpecified() && this.mappedByRelationship) {
+ messages.add(
+ this.buildMessage(
+ JpaValidationMessages.ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_COLUMN_SPECIFIED,
+ EMPTY_STRING_ARRAY,
+ this.column.getValidationTextRange(astRoot)
+ )
+ );
+ }
+
+ this.generatorContainer.validate(messages, reporter, astRoot);
+ if (this.generatedValue != null) {
+ this.generatedValue.validate(messages, reporter, astRoot);
+ }
+ this.converter.validate(messages, reporter, astRoot);
+ }
+
+ protected IMessage buildMessage(String msgID, String[] parms, TextRange textRange) {
+ String attributeDescription = NLS.bind(JpaValidationDescriptionMessages.ATTRIBUTE_DESC, this.getPersistentAttribute().getName());
+ parms = ArrayTools.add(parms, 0, attributeDescription);
+ return DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ msgID,
+ parms,
+ this,
+ textRange
+ );
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMappingDefinition.java
new file mode 100644
index 0000000000..1ba4b92315
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaIdMappingDefinition.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.GeneratedValueAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.IdAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SequenceGeneratorAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TableGeneratorAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TemporalAnnotation;
+
+public abstract class AbstractJavaIdMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaIdMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.ID_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return IdAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ ColumnAnnotation.ANNOTATION_NAME,
+ GeneratedValueAnnotation.ANNOTATION_NAME,
+ TemporalAnnotation.ANNOTATION_NAME,
+ TableGeneratorAnnotation.ANNOTATION_NAME,
+ SequenceGeneratorAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaIdMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinColumnRelationshipStrategy.java
new file mode 100644
index 0000000000..b133a319f7
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinColumnRelationshipStrategy.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.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.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SingleElementListIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.jpa.core.context.JoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public abstract class AbstractJavaJoinColumnRelationshipStrategy
+ extends AbstractJavaJpaContextNode
+ implements JavaJoinColumnRelationshipStrategy
+{
+ protected final Vector<JavaJoinColumn> specifiedJoinColumns = new Vector<JavaJoinColumn>();
+ protected final SpecifiedJoinColumnContainerAdapter specifiedJoinColumnContainerAdapter;
+ protected final JavaJoinColumn.Owner joinColumnOwner;
+
+ protected JavaJoinColumn defaultJoinColumn;
+
+
+ protected AbstractJavaJoinColumnRelationshipStrategy(JavaJoinColumnRelationship parent) {
+ super(parent);
+ this.specifiedJoinColumnContainerAdapter = this.buildSpecifiedJoinColumnContainerAdapter();
+ this.joinColumnOwner = this.buildJoinColumnOwner();
+ this.initializeSpecifiedJoinColumns();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.syncSpecifiedJoinColumns();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateNodes(this.getSpecifiedJoinColumns());
+ this.updateDefaultJoinColumn();
+ }
+
+
+ // ********** join columns **********
+
+ public ListIterator<JavaJoinColumn> joinColumns() {
+ return this.getJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaJoinColumn> getJoinColumns() {
+ return this.hasSpecifiedJoinColumns() ? this.getSpecifiedJoinColumns() : this.getDefaultJoinColumns();
+ }
+
+ public int joinColumnsSize() {
+ return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumnsSize() : this.getDefaultJoinColumnsSize();
+ }
+
+
+ // ********** specified join columns **********
+
+ public ListIterator<JavaJoinColumn> specifiedJoinColumns() {
+ return this.getSpecifiedJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaJoinColumn> getSpecifiedJoinColumns() {
+ return new LiveCloneListIterable<JavaJoinColumn>(this.specifiedJoinColumns);
+ }
+
+ public int specifiedJoinColumnsSize() {
+ return this.specifiedJoinColumns.size();
+ }
+
+ public boolean hasSpecifiedJoinColumns() {
+ return this.specifiedJoinColumns.size() != 0;
+ }
+
+ public JavaJoinColumn getSpecifiedJoinColumn(int index) {
+ return this.specifiedJoinColumns.get(index);
+ }
+
+ public JavaJoinColumn addSpecifiedJoinColumn() {
+ return this.addSpecifiedJoinColumn(this.specifiedJoinColumns.size());
+ }
+
+ public JavaJoinColumn addSpecifiedJoinColumn(int index) {
+ JoinColumnAnnotation annotation = this.addJoinColumnAnnotation(index);
+ return this.addSpecifiedJoinColumn_(index, annotation);
+ }
+
+ public void removeSpecifiedJoinColumn(JoinColumn joinColumn) {
+ this.removeSpecifiedJoinColumn(this.specifiedJoinColumns.indexOf(joinColumn));
+ }
+
+ public void removeSpecifiedJoinColumn(int index) {
+ this.removeJoinColumnAnnotation(index);
+ this.removeSpecifiedJoinColumn_(index);
+ }
+
+ protected void removeSpecifiedJoinColumn_(int index) {
+ this.removeItemFromList(index, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ }
+
+ public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) {
+ this.moveJoinColumnAnnotation(targetIndex, sourceIndex);
+ this.moveItemInList(targetIndex, sourceIndex, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ }
+
+ protected void initializeSpecifiedJoinColumns() {
+ for (JoinColumnAnnotation joinColumnAnnotation : this.getJoinColumnAnnotations()) {
+ this.specifiedJoinColumns.add(this.buildJoinColumn(joinColumnAnnotation));
+ }
+ }
+
+ protected void syncSpecifiedJoinColumns() {
+ ContextContainerTools.synchronizeWithResourceModel(this.specifiedJoinColumnContainerAdapter);
+ }
+
+ protected Iterable<JoinColumnAnnotation> getJoinColumnAnnotations() {
+ return CollectionTools.iterable(this.joinColumnAnnotations());
+ }
+
+ protected void moveSpecifiedJoinColumn_(int index, JavaJoinColumn joinColumn) {
+ this.moveItemInList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ }
+
+ protected JavaJoinColumn addSpecifiedJoinColumn_(int index, JoinColumnAnnotation joinColumnAnnotation) {
+ JavaJoinColumn joinColumn = this.buildJoinColumn(joinColumnAnnotation);
+ this.addItemToList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ return joinColumn;
+ }
+
+ protected void removeSpecifiedJoinColumn_(JavaJoinColumn joinColumn) {
+ this.removeSpecifiedJoinColumn_(this.specifiedJoinColumns.indexOf(joinColumn));
+ }
+
+ protected SpecifiedJoinColumnContainerAdapter buildSpecifiedJoinColumnContainerAdapter() {
+ return new SpecifiedJoinColumnContainerAdapter();
+ }
+
+ /**
+ * specified join column container adapter
+ */
+ protected class SpecifiedJoinColumnContainerAdapter
+ implements ContextContainerTools.Adapter<JavaJoinColumn, JoinColumnAnnotation>
+ {
+ public Iterable<JavaJoinColumn> getContextElements() {
+ return AbstractJavaJoinColumnRelationshipStrategy.this.getSpecifiedJoinColumns();
+ }
+ public Iterable<JoinColumnAnnotation> getResourceElements() {
+ return AbstractJavaJoinColumnRelationshipStrategy.this.getJoinColumnAnnotations();
+ }
+ public JoinColumnAnnotation getResourceElement(JavaJoinColumn contextElement) {
+ return contextElement.getColumnAnnotation();
+ }
+ public void moveContextElement(int index, JavaJoinColumn element) {
+ AbstractJavaJoinColumnRelationshipStrategy.this.moveSpecifiedJoinColumn_(index, element);
+ }
+ public void addContextElement(int index, JoinColumnAnnotation resourceElement) {
+ AbstractJavaJoinColumnRelationshipStrategy.this.addSpecifiedJoinColumn_(index, resourceElement);
+ }
+ public void removeContextElement(JavaJoinColumn element) {
+ AbstractJavaJoinColumnRelationshipStrategy.this.removeSpecifiedJoinColumn_(element);
+ }
+ }
+
+ protected abstract JavaJoinColumn.Owner buildJoinColumnOwner();
+
+
+ // ********** default join column **********
+
+ public JavaJoinColumn getDefaultJoinColumn() {
+ return this.defaultJoinColumn;
+ }
+
+ protected void setDefaultJoinColumn(JavaJoinColumn joinColumn) {
+ JavaJoinColumn old = this.defaultJoinColumn;
+ this.defaultJoinColumn = joinColumn;
+ this.firePropertyChanged(DEFAULT_JOIN_COLUMN_PROPERTY, old, joinColumn);
+ }
+
+ protected ListIterable<JavaJoinColumn> getDefaultJoinColumns() {
+ return (this.defaultJoinColumn != null) ?
+ new SingleElementListIterable<JavaJoinColumn>(this.defaultJoinColumn) :
+ EmptyListIterable.<JavaJoinColumn>instance();
+ }
+
+ protected int getDefaultJoinColumnsSize() {
+ return (this.defaultJoinColumn == null) ? 0 : 1;
+ }
+
+ protected void updateDefaultJoinColumn() {
+ if (this.buildsDefaultJoinColumn()) {
+ if (this.defaultJoinColumn == null) {
+ this.setDefaultJoinColumn(this.buildJoinColumn(this.buildNullJoinColumnAnnotation()));
+ } else {
+ this.defaultJoinColumn.update();
+ }
+ } else {
+ this.setDefaultJoinColumn(null);
+ }
+ }
+
+ protected boolean buildsDefaultJoinColumn() {
+ return ! this.hasSpecifiedJoinColumns() &&
+ this.getRelationship().mayHaveDefaultJoinColumn();
+ }
+
+
+ // ********** join column annotations **********
+
+ protected abstract Iterator<JoinColumnAnnotation> joinColumnAnnotations();
+
+ protected abstract JoinColumnAnnotation addJoinColumnAnnotation(int index);
+
+ protected abstract void removeJoinColumnAnnotation(int index);
+
+ protected abstract void moveJoinColumnAnnotation(int targetIndex, int sourceIndex);
+
+ protected abstract JoinColumnAnnotation buildNullJoinColumnAnnotation();
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaJoinColumnRelationship getParent() {
+ return (JavaJoinColumnRelationship) super.getParent();
+ }
+
+ public JavaJoinColumnRelationship getRelationship() {
+ return this.getParent();
+ }
+
+ protected JavaJoinColumn buildJoinColumn(JoinColumnAnnotation joinColumnAnnotation) {
+ return this.getJpaFactory().buildJavaJoinColumn(this, this.joinColumnOwner, joinColumnAnnotation);
+ }
+
+ public void initializeFrom(ReadOnlyJoinColumnRelationshipStrategy oldStrategy) {
+ for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(oldStrategy.specifiedJoinColumns())) {
+ this.addSpecifiedJoinColumn().initializeFrom(joinColumn);
+ }
+ }
+
+ public void initializeFromVirtual(ReadOnlyJoinColumnRelationshipStrategy virtualStrategy) {
+ for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(virtualStrategy.joinColumns())) {
+ this.addSpecifiedJoinColumn().initializeFromVirtual(joinColumn);
+ }
+ }
+
+ public RelationshipMapping getRelationshipMapping() {
+ return this.getRelationship().getMapping();
+ }
+
+ public String getTableName() {
+ TypeMapping typeMapping = this.getRelationshipSource();
+ return (typeMapping == null) ? null : typeMapping.getPrimaryTableName();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ TypeMapping typeMapping = this.getRelationshipSource();
+ return (typeMapping == null) ? null : typeMapping.resolveDbTable(tableName);
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ TypeMapping typeMapping = this.getRelationshipSource();
+ return (typeMapping != null) && typeMapping.tableNameIsInvalid(tableName);
+ }
+
+ // subclasses like this to be public
+ public Table getReferencedColumnDbTable() {
+ TypeMapping relationshipTarget = this.getRelationshipTarget();
+ return (relationshipTarget == null) ? null : relationshipTarget.getPrimaryDbTable();
+ }
+
+ protected Iterator<String> candidateTableNames() {
+ TypeMapping typeMapping = this.getRelationshipSource();
+ return (typeMapping != null) ? typeMapping.allAssociatedTableNames() : EmptyIterator.<String>instance();
+ }
+
+ public void addStrategy() {
+ if (this.specifiedJoinColumnsSize() == 0) {
+ this.addSpecifiedJoinColumn();
+ }
+ }
+
+ public void removeStrategy() {
+ for (int i = this.specifiedJoinColumns.size(); i-- > 0; ) {
+ this.removeSpecifiedJoinColumn(i);
+ }
+ }
+
+
+ // ********** 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 joinColumn : this.getJoinColumns()) {
+ result = joinColumn.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 (JavaJoinColumn joinColumn : this.getJoinColumns()) {
+ joinColumn.validate(messages, reporter, astRoot);
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinTableRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinTableRelationshipStrategy.java
new file mode 100644
index 0000000000..6eafead62c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJoinTableRelationshipStrategy.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTable;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.Table;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
+import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public abstract class AbstractJavaJoinTableRelationshipStrategy
+ extends AbstractJavaJpaContextNode
+ implements JavaJoinTableRelationshipStrategy, Table.Owner
+{
+ protected JavaJoinTable joinTable;
+
+
+ protected AbstractJavaJoinTableRelationshipStrategy(JavaJoinTableRelationship parent) {
+ super(parent);
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ if (this.joinTable != null) {
+ this.joinTable.synchronizeWithResourceModel();
+ }
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateJoinTable();
+ }
+
+
+ // ********** join table **********
+
+ public JavaJoinTable getJoinTable() {
+ return this.joinTable;
+ }
+
+ protected void setJoinTable(JavaJoinTable joinTable) {
+ JavaJoinTable old = this.joinTable;
+ this.joinTable = joinTable;
+ this.firePropertyChanged(JOIN_TABLE_PROPERTY, old, joinTable);
+ }
+
+ protected void updateJoinTable() {
+ if (this.buildsJoinTable()) {
+ if (this.joinTable == null) {
+ this.setJoinTable(this.buildJoinTable());
+ } else {
+ this.joinTable.update();
+ }
+ } else {
+ if (this.joinTable != null) {
+ this.setJoinTable(null);
+ }
+ }
+ }
+
+ /**
+ * The strategy can have a join table if either the table annotation is present
+ * or the [mapping] relationship supports a default join table.
+ */
+ protected boolean buildsJoinTable() {
+ return this.getJoinTableAnnotation().isSpecified()
+ || this.getRelationship().mayHaveDefaultJoinTable();
+ }
+
+ protected JavaJoinTable buildJoinTable() {
+ return this.getJpaFactory().buildJavaJoinTable(this, this);
+ }
+
+
+ // ********** join table annotation **********
+
+ protected abstract JoinTableAnnotation addJoinTableAnnotation();
+
+ protected abstract void removeJoinTableAnnotation();
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaJoinTableRelationship getParent() {
+ return (JavaJoinTableRelationship) super.getParent();
+ }
+
+ public JavaJoinTableRelationship getRelationship() {
+ return this.getParent();
+ }
+
+ public RelationshipMapping getRelationshipMapping() {
+ return this.getRelationship().getMapping();
+ }
+
+ public void initializeFrom(ReadOnlyJoinTableRelationshipStrategy oldStrategy) {
+ ReadOnlyJoinTable oldJoinTable = oldStrategy.getJoinTable();
+ if (oldJoinTable != null) {
+ this.addStrategy();
+ this.joinTable.initializeFrom(oldJoinTable);
+ }
+ }
+
+ public void initializeFromVirtual(ReadOnlyJoinTableRelationshipStrategy virtualStrategy) {
+ ReadOnlyJoinTable oldJoinTable = virtualStrategy.getJoinTable();
+ if (oldJoinTable != null) {
+ this.addStrategy();
+ this.joinTable.initializeFromVirtual(oldJoinTable);
+ }
+ }
+
+ public String getTableName() {
+ return (this.joinTable == null) ? null : this.joinTable.getName();
+ }
+
+ public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) {
+ return (this.joinTable == null) ? null : this.joinTable.getDbTable();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return Tools.valuesAreDifferent(this.getTableName(), tableName);
+ }
+
+ public String getColumnTableNotValidDescription() {
+ return JpaValidationDescriptionMessages.DOES_NOT_MATCH_JOIN_TABLE;
+ }
+
+ public String getJoinTableDefaultName() {
+ return MappingTools.buildJoinTableDefaultName(this.getRelationship());
+ }
+
+ public void addStrategy() {
+ if (this.joinTable == null) {
+ this.addJoinTableAnnotation();
+ this.setJoinTable(this.buildJoinTable());
+ }
+ }
+
+ public void removeStrategy() {
+ if (this.joinTable != null) {
+ this.removeJoinTableAnnotation();
+ this.setJoinTable(null);
+ }
+ }
+
+
+ // ********** 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;
+ }
+ if (this.joinTable != null) {
+ result = this.joinTable.javaCompletionProposals(pos, filter, astRoot);
+ }
+ return result;
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ if (this.joinTable != null) {
+ this.joinTable.validate(messages, reporter, astRoot);
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJpaContextNode.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJpaContextNode.java
new file mode 100644
index 0000000000..92643cc26a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaJpaContextNode.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.JptCommonCorePlugin;
+import org.eclipse.jpt.common.core.JptResourceType;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.context.JpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.internal.context.AbstractJpaContextNode;
+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;
+
+public abstract class AbstractJavaJpaContextNode
+ extends AbstractJpaContextNode
+ implements JavaJpaContextNode
+{
+ protected AbstractJavaJpaContextNode(JpaContextNode parent) {
+ super(parent);
+ }
+
+ @Override
+ public JptResourceType getResourceType() {
+ return JptCommonCorePlugin.JAVA_SOURCE_RESOURCE_TYPE;
+ }
+
+ public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
+ if (this.connectionProfileIsActive()) {
+ Iterator<String> result = this.connectedJavaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This method is called if the database is connected, allowing us to
+ * get candidates from the various database tables etc.
+ * This method should NOT be cascaded to "child" objects; it should
+ * only return candidates for the current object. The cascading is
+ * handled by #javaCompletionProposals(int, Filter, CompilationUnit).
+ */
+ @SuppressWarnings("unused")
+ public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
+ return null;
+ }
+
+ // ********** validation **********
+
+ /**
+ * All subclass implementations
+ * should be preceded by a "super" call to this method.
+ */
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ if (reporter.isCancelled()) {
+ throw new ValidationCancelledException();
+ }
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMapping.java
new file mode 100644
index 0000000000..22c5d8c9e3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMapping.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaManyToManyRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappingRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaManyToManyMapping2_0;
+import org.eclipse.jpt.jpa.core.resource.java.ManyToManyAnnotation;
+
+public abstract class AbstractJavaManyToManyMapping
+ extends AbstractJavaMultiRelationshipMapping<ManyToManyAnnotation>
+ implements JavaManyToManyMapping2_0
+{
+ protected AbstractJavaManyToManyMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ }
+
+
+ // ********** relationship **********
+
+ @Override
+ public JavaManyToManyRelationship getRelationship() {
+ return (JavaManyToManyRelationship) super.getRelationship();
+ }
+
+ @Override
+ protected JavaMappingRelationship buildRelationship() {
+ return new GenericJavaManyToManyRelationship(this);
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return ManyToManyAnnotation.ANNOTATION_NAME;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMappingDefinition.java
new file mode 100644
index 0000000000..9677d6b81e
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToManyMappingDefinition.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.ManyToManyAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.MapKeyAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.OrderByAnnotation;
+
+public abstract class AbstractJavaManyToManyMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaManyToManyMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return ManyToManyAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ JoinTableAnnotation.ANNOTATION_NAME,
+ MapKeyAnnotation.ANNOTATION_NAME,
+ OrderByAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaManyToManyMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMapping.java
new file mode 100644
index 0000000000..42a93b9b37
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMapping.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaManyToOneRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaManyToOneMapping2_0;
+import org.eclipse.jpt.jpa.core.resource.java.ManyToOneAnnotation;
+
+public abstract class AbstractJavaManyToOneMapping
+ extends AbstractJavaSingleRelationshipMapping<ManyToOneAnnotation>
+ implements JavaManyToOneMapping2_0
+{
+ protected AbstractJavaManyToOneMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ }
+
+
+ // ********** relationship **********
+
+ @Override
+ public JavaManyToOneRelationship getRelationship() {
+ return (JavaManyToOneRelationship) super.getRelationship();
+ }
+
+ @Override
+ protected JavaManyToOneRelationship buildRelationship() {
+ return new GenericJavaManyToOneRelationship(this);
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return ManyToOneAnnotation.ANNOTATION_NAME;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMappingDefinition.java
new file mode 100644
index 0000000000..9534ff5126
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaManyToOneMappingDefinition.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.ManyToOneAnnotation;
+
+public abstract class AbstractJavaManyToOneMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaManyToOneMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return ManyToOneAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ JoinTableAnnotation.ANNOTATION_NAME,
+ JoinColumnAnnotation.ANNOTATION_NAME,
+ JoinColumnsAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaManyToOneMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappedSuperclass.java
new file mode 100644
index 0000000000..b4255f5a56
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappedSuperclass.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaIdClassReference;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedSuperclass;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericMappedSuperclassPrimaryKeyValidator;
+import org.eclipse.jpt.jpa.core.resource.java.MappedSuperclassAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java mapped superclass
+ */
+public abstract class AbstractJavaMappedSuperclass
+ extends AbstractJavaTypeMapping<MappedSuperclassAnnotation>
+ implements JavaMappedSuperclass
+{
+ protected final JavaIdClassReference idClassReference;
+
+
+ protected AbstractJavaMappedSuperclass(JavaPersistentType parent, MappedSuperclassAnnotation mappingAnnotation) {
+ super(parent, mappingAnnotation);
+ this.idClassReference = this.buildIdClassReference();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.idClassReference.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.idClassReference.update();
+ }
+
+
+ // ********** id class **********
+
+ public JavaIdClassReference getIdClassReference() {
+ return this.idClassReference;
+ }
+
+ protected JavaIdClassReference buildIdClassReference() {
+ return new GenericJavaIdClassReference(this);
+ }
+
+ public JavaPersistentType getIdClass() {
+ return this.idClassReference.getIdClass();
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.MAPPED_SUPERCLASS_TYPE_MAPPING_KEY;
+ }
+
+ public boolean isMapped() {
+ return true;
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return false;
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.validatePrimaryKey(messages, reporter, astRoot);
+ }
+
+ @Override
+ public boolean validatesAgainstDatabase() {
+ return false;
+ }
+
+ protected void validatePrimaryKey(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.buildPrimaryKeyValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildPrimaryKeyValidator(CompilationUnit astRoot) {
+ return new GenericMappedSuperclassPrimaryKeyValidator(this, this.buildTextRangeResolver(astRoot));
+ // TODO - JPA 2.0 validation
+ }
+
+ @Override
+ protected PrimaryKeyTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaMappedSuperclassTextRangeResolver(this, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappingRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappingRelationship.java
new file mode 100644
index 0000000000..852474ce29
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMappingRelationship.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.MappedByRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyRelationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappingRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+
+/**
+ * <strong>NB:</strong> Subclasses may want to set the {@link #strategy} at the
+ * end of their constructors; otherwise, it will be <code>null</code> until it
+ * is set during {@link #update()}.
+ */
+public abstract class AbstractJavaMappingRelationship<M extends JavaRelationshipMapping>
+ extends AbstractJavaJpaContextNode
+ implements JavaMappingRelationship
+{
+ protected JavaRelationshipStrategy strategy;
+
+
+ public AbstractJavaMappingRelationship(M parent) {
+ super(parent);
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateStrategy();
+ }
+
+
+ // ********** strategy **********
+
+ public JavaRelationshipStrategy getStrategy() {
+ return this.strategy;
+ }
+
+ protected void setStrategy(JavaRelationshipStrategy strategy) {
+ RelationshipStrategy old = this.strategy;
+ this.strategy = strategy;
+ this.firePropertyChanged(STRATEGY_PROPERTY, old, strategy);
+ }
+
+ protected abstract JavaRelationshipStrategy buildStrategy();
+
+ /**
+ * This is called by subclasses when the various supported strategies are
+ * added or removed; allowing the strategy to be set synchronously. (?)
+ */
+ protected void updateStrategy() {
+ this.setStrategy(this.buildStrategy());
+ }
+
+
+ // ********** conversions **********
+
+ public void initializeFrom(ReadOnlyRelationship oldRelationship) {
+ oldRelationship.initializeOn(this);
+ }
+
+ public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) {
+ // NOP
+ }
+
+ public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) {
+ // NOP
+ }
+
+ public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) {
+ // NOP
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public M getParent() {
+ return (M) super.getParent();
+ }
+
+ public JavaRelationshipMapping getMapping() {
+ return this.getParent();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return this.getMapping().getTypeMapping();
+ }
+
+ public Entity getEntity() {
+ TypeMapping typeMapping = this.getTypeMapping();
+ return (typeMapping instanceof Entity) ? (Entity) typeMapping : null;
+ }
+
+ public boolean isOverridable() {
+ return this.strategy.isOverridable();
+ }
+
+ public boolean isVirtual() {
+ return this.getMapping().getPersistentAttribute().isVirtual();
+ }
+
+ public boolean isTargetForeignKey() {
+ return false;
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getMapping().getValidationTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMultiRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMultiRelationshipMapping.java
new file mode 100644
index 0000000000..bb0e245fe8
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaMultiRelationshipMapping.java
@@ -0,0 +1,780 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.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.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeOverride;
+import org.eclipse.jpt.jpa.core.context.AttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Column;
+import org.eclipse.jpt.jpa.core.context.Embeddable;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.FetchType;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.OverrideContainer;
+import org.eclipse.jpt.jpa.core.context.Override_;
+import org.eclipse.jpt.jpa.core.context.RelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaMultiRelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaOrderable;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EmbeddableOverrideDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.MapKeyAttributeOverrideColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.MapKeyAttributeOverrideValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.MapKeyColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.RelationshipStrategyTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.NullJavaMapKeyColumn2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.Orderable2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaCollectionMapping2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentAttribute2_0;
+import org.eclipse.jpt.jpa.core.jpa2.resource.java.MapKeyClass2_0Annotation;
+import org.eclipse.jpt.jpa.core.jpa2.resource.java.MapKeyColumn2_0Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember;
+import org.eclipse.jpt.jpa.core.resource.java.MapKeyAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.RelationshipMappingAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java multi-relationship (m:m, 1:m) mapping
+ */
+public abstract class AbstractJavaMultiRelationshipMapping<A extends RelationshipMappingAnnotation>
+ extends AbstractJavaRelationshipMapping<A>
+ implements JavaMultiRelationshipMapping, JavaCollectionMapping2_0
+{
+ protected final JavaOrderable orderable;
+
+ protected String specifiedMapKey;
+ protected boolean noMapKey = false;
+ protected boolean pkMapKey = false;
+ protected boolean customMapKey = false;
+
+ protected String specifiedMapKeyClass;
+ protected String defaultMapKeyClass;
+ protected String fullyQualifiedMapKeyClass;
+
+ protected Type valueType;
+ protected Type keyType;
+
+ protected final JavaColumn mapKeyColumn;
+
+ protected final JavaAttributeOverrideContainer mapKeyAttributeOverrideContainer;
+
+
+ protected AbstractJavaMultiRelationshipMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.orderable = this.buildOrderable();
+
+ this.specifiedMapKey = this.buildSpecifiedMapKey();
+ this.noMapKey = this.buildNoMapKey();
+ this.pkMapKey = this.buildPkMapKey();
+ this.customMapKey = this.buildCustomMapKey();
+
+ this.specifiedMapKeyClass = this.buildSpecifiedMapKeyClass();
+
+ this.mapKeyColumn = this.buildMapKeyColumn();
+ this.mapKeyAttributeOverrideContainer = this.buildMapKeyAttributeOverrideContainer();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.orderable.synchronizeWithResourceModel();
+
+ this.setSpecifiedMapKey_(this.buildSpecifiedMapKey());
+ this.setNoMapKey_(this.buildNoMapKey());
+ this.setPkMapKey_(this.buildPkMapKey());
+ this.setCustomMapKey_(this.buildCustomMapKey());
+
+ this.setSpecifiedMapKeyClass_(this.buildSpecifiedMapKeyClass());
+
+ this.mapKeyColumn.synchronizeWithResourceModel();
+
+ this.mapKeyAttributeOverrideContainer.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+
+ this.orderable.update();
+
+ this.setDefaultMapKeyClass(this.buildDefaultMapKeyClass());
+ this.setFullyQualifiedMapKeyClass(this.buildFullyQualifiedMapKeyClass());
+
+ this.setValueType(this.buildValueType());
+ this.setKeyType(this.buildKeyType());
+
+ this.mapKeyColumn.update();
+
+ this.mapKeyAttributeOverrideContainer.update();
+ }
+
+
+ // ********** orderable **********
+
+ public JavaOrderable getOrderable() {
+ return this.orderable;
+ }
+
+ protected JavaOrderable buildOrderable() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildJavaOrderable(this, this.buildOrderableOwner()) :
+ this.getJpaFactory().buildJavaOrderable(this);
+ }
+
+ protected Orderable2_0.Owner buildOrderableOwner() {
+ return new OrderableOwner();
+ }
+
+ protected class OrderableOwner
+ implements Orderable2_0.Owner
+ {
+ public String getTableName() {
+ return this.getRelationshipStrategy().getTableName();
+ }
+ public Table resolveDbTable(String tableName) {
+ return this.getRelationshipStrategy().resolveDbTable(tableName);
+ }
+ protected JavaRelationshipStrategy getRelationshipStrategy() {
+ return AbstractJavaMultiRelationshipMapping.this.getRelationship().getStrategy();
+ }
+ }
+
+
+ // ********** map key **********
+
+ public String getMapKey() {
+ if (this.noMapKey) {
+ return null;
+ }
+ if (this.pkMapKey) {
+ return this.getTargetEntityIdAttributeName();
+ }
+ if (this.customMapKey) {
+ return this.specifiedMapKey;
+ }
+ throw new IllegalStateException("unknown map key"); //$NON-NLS-1$
+ }
+
+
+ // ********** specified map key **********
+
+ public String getSpecifiedMapKey() {
+ return this.specifiedMapKey;
+ }
+
+ public void setSpecifiedMapKey(String mapKey) {
+ if (mapKey != null) {
+ this.getMapKeyAnnotationForUpdate().setName(mapKey);
+
+ this.setSpecifiedMapKey_(mapKey);
+ this.setNoMapKey_(false);
+ this.setPkMapKey_(false);
+ this.setCustomMapKey_(true);
+ } else {
+ this.setPkMapKey(true); // hmmm...
+ }
+ }
+
+ protected void setSpecifiedMapKey_(String mapKey) {
+ String old = this.specifiedMapKey;
+ this.specifiedMapKey = mapKey;
+ this.firePropertyChanged(SPECIFIED_MAP_KEY_PROPERTY, old, mapKey);
+ }
+
+ protected String buildSpecifiedMapKey() {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ return (mapKeyAnnotation == null) ? null : mapKeyAnnotation.getName();
+ }
+
+
+ // ********** no map key **********
+
+ public boolean isNoMapKey() {
+ return this.noMapKey;
+ }
+
+ public void setNoMapKey(boolean noMapKey) {
+ if (noMapKey) {
+ if (this.getMapKeyAnnotation() != null) {
+ this.removeMapKeyAnnotation();
+ }
+
+ this.setSpecifiedMapKey_(null);
+ this.setNoMapKey_(true);
+ this.setPkMapKey_(false);
+ this.setCustomMapKey_(false);
+ } else {
+ this.setPkMapKey(true); // hmmm...
+ }
+ }
+
+ protected void setNoMapKey_(boolean noMapKey) {
+ boolean old = this.noMapKey;
+ this.noMapKey = noMapKey;
+ this.firePropertyChanged(NO_MAP_KEY_PROPERTY, old, noMapKey);
+ }
+
+ protected boolean buildNoMapKey() {
+ return this.getMapKeyAnnotation() == null;
+ }
+
+
+ // ********** pk map key **********
+
+ public boolean isPkMapKey() {
+ return this.pkMapKey;
+ }
+
+ public void setPkMapKey(boolean pkMapKey) {
+ if (pkMapKey) {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ if (mapKeyAnnotation == null) {
+ mapKeyAnnotation = this.addMapKeyAnnotation();
+ } else {
+ mapKeyAnnotation.setName(null);
+ }
+
+ this.setSpecifiedMapKey_(null);
+ this.setNoMapKey_(false);
+ this.setPkMapKey_(true);
+ this.setCustomMapKey_(false);
+ } else {
+ this.setNoMapKey(true); // hmmm...
+ }
+ }
+
+ protected void setPkMapKey_(boolean pkMapKey) {
+ boolean old = this.pkMapKey;
+ this.pkMapKey = pkMapKey;
+ this.firePropertyChanged(PK_MAP_KEY_PROPERTY, old, pkMapKey);
+ }
+
+ protected boolean buildPkMapKey() {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ return (mapKeyAnnotation != null) && (mapKeyAnnotation.getName() == null);
+ }
+
+
+ // ********** custom map key **********
+
+ public boolean isCustomMapKey() {
+ return this.customMapKey;
+ }
+
+ public void setCustomMapKey(boolean customMapKey) {
+ if (customMapKey) {
+ this.setSpecifiedMapKey(""); //$NON-NLS-1$
+ } else {
+ this.setNoMapKey(true); // hmmm...
+ }
+ }
+
+ protected void setCustomMapKey_(boolean customMapKey) {
+ boolean old = this.customMapKey;
+ this.customMapKey = customMapKey;
+ this.firePropertyChanged(CUSTOM_MAP_KEY_PROPERTY, old, customMapKey);
+ }
+
+ protected boolean buildCustomMapKey() {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ return (mapKeyAnnotation != null) && (mapKeyAnnotation.getName() != null);
+ }
+
+
+ // ********** map key annotation **********
+
+ protected MapKeyAnnotation getMapKeyAnnotation() {
+ return (MapKeyAnnotation) this.getResourcePersistentAttribute().getAnnotation(MapKeyAnnotation.ANNOTATION_NAME);
+ }
+
+ protected MapKeyAnnotation getMapKeyAnnotationForUpdate() {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ return (mapKeyAnnotation != null) ? mapKeyAnnotation : this.addMapKeyAnnotation();
+ }
+
+ protected MapKeyAnnotation addMapKeyAnnotation() {
+ return (MapKeyAnnotation) this.getResourcePersistentAttribute().addAnnotation(MapKeyAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void removeMapKeyAnnotation() {
+ this.getResourcePersistentAttribute().removeAnnotation(MapKeyAnnotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** map key class **********
+
+ public String getMapKeyClass() {
+ return (this.specifiedMapKeyClass != null) ? this.specifiedMapKeyClass : this.defaultMapKeyClass;
+ }
+
+ public String getSpecifiedMapKeyClass() {
+ return this.specifiedMapKeyClass;
+ }
+
+ public void setSpecifiedMapKeyClass(String mapKeyClass) {
+ if (this.valuesAreDifferent(mapKeyClass, this.specifiedMapKeyClass)) {
+ MapKeyClass2_0Annotation annotation = this.getMapKeyClassAnnotation();
+ if (mapKeyClass == null) {
+ if (annotation != null) {
+ this.removeMapKeyClassAnnotation();
+ }
+ } else {
+ if (annotation == null) {
+ annotation = this.addMapKeyClassAnnotation();
+ }
+ annotation.setValue(mapKeyClass);
+ }
+
+ this.setSpecifiedMapKeyClass_(mapKeyClass);
+ }
+ }
+
+ protected void setSpecifiedMapKeyClass_(String mapKeyClass) {
+ String old = this.specifiedMapKeyClass;
+ this.specifiedMapKeyClass = mapKeyClass;
+ this.firePropertyChanged(SPECIFIED_MAP_KEY_CLASS_PROPERTY, old, mapKeyClass);
+ }
+
+ protected String buildSpecifiedMapKeyClass() {
+ MapKeyClass2_0Annotation annotation = this.getMapKeyClassAnnotation();
+ return (annotation == null) ? null : annotation.getValue();
+ }
+
+ public String getDefaultMapKeyClass() {
+ return this.defaultMapKeyClass;
+ }
+
+ protected void setDefaultMapKeyClass(String mapKeyClass) {
+ String old = this.defaultMapKeyClass;
+ this.defaultMapKeyClass = mapKeyClass;
+ this.firePropertyChanged(DEFAULT_MAP_KEY_CLASS_PROPERTY, old, mapKeyClass);
+ }
+
+ protected String buildDefaultMapKeyClass() {
+ return this.isJpa2_0Compatible() ? this.getPersistentAttribute().getMultiReferenceMapKeyTypeName() : null;
+ }
+
+ public String getFullyQualifiedMapKeyClass() {
+ return this.fullyQualifiedMapKeyClass;
+ }
+
+ protected void setFullyQualifiedMapKeyClass(String mapKeyClass) {
+ String old = this.fullyQualifiedMapKeyClass;
+ this.fullyQualifiedMapKeyClass = mapKeyClass;
+ this.firePropertyChanged(FULLY_QUALIFIED_MAP_KEY_CLASS_PROPERTY, old, mapKeyClass);
+ }
+
+ protected String buildFullyQualifiedMapKeyClass() {
+ return this.isJpa2_0Compatible() ? this.buildFullyQualifiedMapKeyClass_() : null;
+ }
+
+ protected String buildFullyQualifiedMapKeyClass_() {
+ return (this.specifiedMapKeyClass == null) ?
+ this.defaultMapKeyClass :
+ this.getMapKeyClassAnnotation().getFullyQualifiedClassName();
+ }
+
+ public char getMapKeyClassEnclosingTypeSeparator() {
+ return '.';
+ }
+
+
+ // ********** resolved map key embeddable/entity **********
+
+ protected Embeddable getResolvedMapKeyEmbeddable() {
+ return this.getPersistenceUnit().getEmbeddable(this.fullyQualifiedMapKeyClass);
+ }
+
+ protected Entity getResolvedMapKeyEntity() {
+ return this.getPersistenceUnit().getEntity(this.fullyQualifiedMapKeyClass);
+ }
+
+
+ // ********** map key class annotation **********
+
+ protected MapKeyClass2_0Annotation getMapKeyClassAnnotation() {
+ return this.isJpa2_0Compatible() ? this.getMapKeyClassAnnotation_() : null;
+ }
+
+ protected MapKeyClass2_0Annotation getMapKeyClassAnnotation_() {
+ return (MapKeyClass2_0Annotation) this.getResourcePersistentAttribute().getAnnotation(MapKeyClass2_0Annotation.ANNOTATION_NAME);
+ }
+
+ protected MapKeyClass2_0Annotation addMapKeyClassAnnotation() {
+ return (MapKeyClass2_0Annotation) this.getResourcePersistentAttribute().addAnnotation(MapKeyClass2_0Annotation.ANNOTATION_NAME);
+ }
+
+ protected void removeMapKeyClassAnnotation() {
+ this.getResourcePersistentAttribute().removeAnnotation(MapKeyClass2_0Annotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** value type **********
+
+ public Type getValueType() {
+ return this.valueType;
+ }
+
+ protected void setValueType(Type valueType) {
+ Type old = this.valueType;
+ this.valueType = valueType;
+ this.firePropertyChanged(VALUE_TYPE_PROPERTY, old, valueType);
+ }
+
+ protected Type buildValueType() {
+ if (this.getResolvedTargetEntity() != null) {
+ return Type.ENTITY_TYPE;
+ }
+ if (this.getResolvedTargetEmbeddable() != null) {
+ return Type.EMBEDDABLE_TYPE;
+ }
+ if (this.getTargetEntity() == null) {
+ return Type.NO_TYPE;
+ }
+ return Type.BASIC_TYPE;
+ }
+
+ protected Embeddable getResolvedTargetEmbeddable() {
+ return this.getPersistenceUnit().getEmbeddable(this.fullyQualifiedTargetEntity);
+ }
+
+
+ // ********** key type **********
+
+ public Type getKeyType() {
+ return this.keyType;
+ }
+
+ protected void setKeyType(Type keyType) {
+ Type old = this.keyType;
+ this.keyType = keyType;
+ this.firePropertyChanged(KEY_TYPE_PROPERTY, old, keyType);
+ }
+
+ protected Type buildKeyType() {
+ if (this.getResolvedMapKeyEmbeddable() != null) {
+ return Type.EMBEDDABLE_TYPE;
+ }
+ if (this.getResolvedMapKeyEntity() != null) {
+ return Type.ENTITY_TYPE;
+ }
+ if (this.getMapKeyClass() == null) {
+ return Type.NO_TYPE;
+ }
+ return Type.BASIC_TYPE;
+ }
+
+
+ // ********** map key column **********
+
+ public JavaColumn getMapKeyColumn() {
+ return this.mapKeyColumn;
+ }
+
+ protected JavaColumn buildMapKeyColumn() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildJavaMapKeyColumn(this, this.buildMapKeyColumnOwner()) :
+ new NullJavaMapKeyColumn2_0(this);
+ }
+
+ protected JavaColumn.Owner buildMapKeyColumnOwner() {
+ return new MapKeyColumnOwner();
+ }
+
+ protected MapKeyColumn2_0Annotation getMapKeyColumnAnnotation() {
+ return this.isJpa2_0Compatible() ? this.getMapKeyColumnAnnotation_() : null;
+ }
+
+ protected MapKeyColumn2_0Annotation getMapKeyColumnAnnotation_() {
+ return (MapKeyColumn2_0Annotation) this.getResourcePersistentAttribute().getNonNullAnnotation(MapKeyColumn2_0Annotation.ANNOTATION_NAME);
+ }
+
+ protected void removeMapKeyColumnAnnotation() {
+ if (this.isJpa2_0Compatible()) {
+ this.removeMapKeyColumnAnnotation_();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ protected void removeMapKeyColumnAnnotation_() {
+ this.getResourcePersistentAttribute().removeAnnotation(MapKeyColumn2_0Annotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** map key attribute override container **********
+
+ public JavaAttributeOverrideContainer getMapKeyAttributeOverrideContainer() {
+ return this.mapKeyAttributeOverrideContainer;
+ }
+
+ public JavaAttributeOverrideContainer buildMapKeyAttributeOverrideContainer() {
+ return this.getJpaFactory().buildJavaAttributeOverrideContainer(this, this.buildMapKeyAttributeOverrideContainerOwner());
+ }
+
+ protected JavaAttributeOverrideContainer.Owner buildMapKeyAttributeOverrideContainerOwner() {
+ return new MapKeyAttributeOverrideContainerOwner();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ protected String buildDefaultTargetEntity() {
+ return this.getPersistentAttribute().getMultiReferenceTargetTypeName();
+ }
+
+ @Override
+ protected FetchType buildDefaultFetch() {
+ return DEFAULT_FETCH_TYPE;
+ }
+
+
+ // ********** 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.orderable.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ if (this.mapKeyNameTouches(pos, astRoot)) {
+ return this.javaCandidateMapKeyNames(filter);
+ }
+
+ result = this.mapKeyColumn.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ result = this.mapKeyAttributeOverrideContainer.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return null;
+ }
+
+ protected boolean mapKeyNameTouches(int pos, CompilationUnit astRoot) {
+ MapKeyAnnotation mapKeyAnnotation = this.getMapKeyAnnotation();
+ return (mapKeyAnnotation != null) && mapKeyAnnotation.nameTouches(pos, astRoot);
+ }
+
+ protected Iterator<String> javaCandidateMapKeyNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.candidateMapKeyNames(filter));
+ }
+
+ protected Iterator<String> candidateMapKeyNames(Filter<String> filter) {
+ return new FilteringIterator<String>(this.candidateMapKeyNames(), filter);
+ }
+
+ public Iterator<String> candidateMapKeyNames() {
+ return this.allTargetEntityAttributeNames();
+ }
+
+
+ // ********** metamodel **********
+
+ @Override
+ protected String getMetamodelFieldTypeName() {
+ return ((JavaPersistentAttribute2_0) this.getPersistentAttribute()).getMetamodelContainerFieldTypeName();
+ }
+
+ @Override
+ protected void addMetamodelFieldTypeArgumentNamesTo(ArrayList<String> typeArgumentNames) {
+ this.addMetamodelFieldMapKeyTypeArgumentNameTo(typeArgumentNames);
+ super.addMetamodelFieldTypeArgumentNamesTo(typeArgumentNames);
+ }
+
+ protected void addMetamodelFieldMapKeyTypeArgumentNameTo(ArrayList<String> typeArgumentNames) {
+ String keyTypeName = ((JavaPersistentAttribute2_0) this.getPersistentAttribute()).getMetamodelContainerFieldMapKeyTypeName();
+ if (keyTypeName != null) {
+ typeArgumentNames.add(keyTypeName);
+ }
+ }
+
+ public String getMetamodelFieldMapKeyTypeName() {
+ return MappingTools.getMetamodelFieldMapKeyTypeName(this);
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.orderable.validate(messages, reporter, astRoot);
+ this.validateMapKey(messages, reporter, astRoot);
+ }
+
+ protected void validateMapKey(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ if (this.getMapKeyAnnotation() != null) {//If MapKey annotation specified, no other MapKey* annotations can be specified, don't validate them
+ //TODO validate that the map key refers to an existing attribute
+ return;
+ }
+ if (this.getKeyType() == Type.BASIC_TYPE) {
+ this.mapKeyColumn.validate(messages, reporter, astRoot);
+ //validate map key converter
+ }
+ else if (this.getKeyType() == Type.ENTITY_TYPE) {
+ //validate map key join columns
+ }
+ else if (this.getKeyType() == Type.EMBEDDABLE_TYPE) {
+ this.mapKeyAttributeOverrideContainer.validate(messages, reporter, astRoot);
+ //validate map key association overrides - for eclipselink
+ }
+ }
+
+
+ // ********** abstract owner **********
+
+ /**
+ * some common behavior
+ */
+ protected abstract class AbstractOwner
+ {
+ public TypeMapping getTypeMapping() {
+ return AbstractJavaMultiRelationshipMapping.this.getTypeMapping();
+ }
+
+ public String getDefaultTableName() {
+ return this.getRelationshipStrategy().getTableName();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return this.getRelationshipStrategy().resolveDbTable(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return EmptyIterator.instance();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return AbstractJavaMultiRelationshipMapping.this.getValidationTextRange(astRoot);
+ }
+
+ protected RelationshipStrategy getRelationshipStrategy() {
+ return AbstractJavaMultiRelationshipMapping.this.getRelationship().getStrategy();
+ }
+ }
+
+
+ // ********** map key column owner **********
+
+ protected class MapKeyColumnOwner
+ extends AbstractOwner
+ implements JavaColumn.Owner
+ {
+ public MapKeyColumn2_0Annotation getColumnAnnotation() {
+ return AbstractJavaMultiRelationshipMapping.this.getMapKeyColumnAnnotation();
+ }
+
+ public void removeColumnAnnotation() {
+ AbstractJavaMultiRelationshipMapping.this.removeMapKeyColumnAnnotation();
+ }
+
+ public String getDefaultColumnName() {
+ return AbstractJavaMultiRelationshipMapping.this.getName() + "_KEY"; //$NON-NLS-1$
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getRelationshipStrategy().tableNameIsInvalid(tableName);
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new MapKeyColumnValidator((BaseColumn) column, (BaseColumnTextRangeResolver) textRangeResolver, new RelationshipStrategyTableDescriptionProvider(this.getRelationshipStrategy()));
+ }
+ }
+
+
+ // ********** map key attribute override owner **********
+
+ protected class MapKeyAttributeOverrideContainerOwner
+ extends AbstractOwner
+ implements JavaAttributeOverrideContainer.Owner
+ {
+ public JavaResourcePersistentMember getResourcePersistentMember() {
+ return AbstractJavaMultiRelationshipMapping.this.getResourcePersistentAttribute();
+ }
+
+ public TypeMapping getOverridableTypeMapping() {
+ return AbstractJavaMultiRelationshipMapping.this.getResolvedMapKeyEmbeddable();
+ }
+
+ /**
+ * If there is a specified table name it needs to be the same
+ * the default table name. the table is always the collection table
+ */
+ public boolean tableNameIsInvalid(String tableName) {
+ return Tools.valuesAreDifferent(this.getDefaultTableName(), tableName);
+ }
+
+ public Iterator<String> allOverridableNames() {
+ TypeMapping typeMapping = this.getOverridableTypeMapping();
+ return (typeMapping != null) ? typeMapping.allOverridableAttributeNames() : EmptyIterator.<String>instance();
+ }
+
+ protected static final String POSSIBLE_PREFIX = "key"; //$NON-NLS-1$
+ public String getPossiblePrefix() {
+ return POSSIBLE_PREFIX;
+ }
+
+ public String getWritePrefix() {
+ return this.getPossiblePrefix();
+ }
+
+ // since only a map's key can be an embeddable on a 1-m or m-m;
+ // all overrides are relevant
+ public boolean isRelevant(String overrideName) {
+ return true;
+ }
+
+ public Column resolveOverriddenColumn(String attributeName) {
+ return MappingTools.resolveOverriddenColumn(this.getOverridableTypeMapping(), attributeName);
+ }
+
+ public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) {
+ return new MapKeyAttributeOverrideValidator((AttributeOverride) override, (AttributeOverrideContainer) container, textRangeResolver, new EmbeddableOverrideDescriptionProvider());
+ }
+
+ public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner owner, BaseColumnTextRangeResolver textRangeResolver) {
+ return new MapKeyAttributeOverrideColumnValidator((AttributeOverride) override, column, textRangeResolver, new RelationshipStrategyTableDescriptionProvider(this.getRelationshipStrategy()));
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaNamedColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaNamedColumn.java
new file mode 100644
index 0000000000..fa129f27da
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaNamedColumn.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyNamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaNamedColumn;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.resource.java.NamedColumnAnnotation;
+import org.eclipse.jpt.jpa.db.Column;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java<ul>
+ * <li>column
+ * <li>join column
+ * <li>discriminator column
+ * <li>order column
+ * <li>primary key join column
+ * </ul>
+ * <strong>NB:</strong> any subclass that directly holds its column annotation
+ * must:<ul>
+ * <li>call the "super" constructor that takes a column annotation
+ * {@link #AbstractJavaNamedColumn(JavaJpaContextNode, JavaNamedColumn.Owner, NamedColumnAnnotation)}
+ * <li>override {@link #setColumnAnnotation(NamedColumnAnnotation)} to set the column annotation
+ * so it is in place before the column's state (e.g. {@link #specifiedName})
+ * is initialized
+ * </ul>
+ */
+public abstract class AbstractJavaNamedColumn<A extends NamedColumnAnnotation, O extends JavaNamedColumn.Owner>
+ extends AbstractJavaJpaContextNode
+ implements JavaNamedColumn
+{
+ protected final O owner;
+
+ protected String specifiedName;
+ protected String defaultName;
+
+ protected String columnDefinition;
+
+
+ protected AbstractJavaNamedColumn(JavaJpaContextNode parent, O owner) {
+ this(parent, owner, null);
+ }
+
+ protected AbstractJavaNamedColumn(JavaJpaContextNode parent, O owner, A columnAnnotation) {
+ super(parent);
+ this.owner = owner;
+ this.setColumnAnnotation(columnAnnotation);
+ this.specifiedName = this.buildSpecifiedName();
+ this.columnDefinition = this.buildColumnDefinition();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedName_(this.buildSpecifiedName());
+ this.setColumnDefinition_(this.buildColumnDefinition());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultName(this.buildDefaultName());
+ }
+
+
+ // ********** column annotation **********
+
+ /**
+ * Return the Java column annotation. Do not return <code>null</code> if the
+ * Java annotation does not exist; return a <em>null</em> column annotation
+ * instead.
+ */
+ public abstract A getColumnAnnotation();
+
+ /**
+ * see class comment... ({@link AbstractJavaNamedColumn})
+ */
+ protected void setColumnAnnotation(A columnAnnotation) {
+ if (columnAnnotation != null) {
+ throw new IllegalArgumentException("this method must be overridden if the column annotation is not null: " + columnAnnotation); //$NON-NLS-1$
+ }
+ }
+
+ protected void removeColumnAnnotationIfUnset() {
+ if (this.getColumnAnnotation().isUnset()) {
+ this.removeColumnAnnotation();
+ }
+ }
+
+ protected abstract void removeColumnAnnotation();
+
+
+ // ********** name **********
+
+ public String getName() {
+ return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
+ }
+
+ public String getSpecifiedName() {
+ return this.specifiedName;
+ }
+
+ public void setSpecifiedName(String name) {
+ if (this.valuesAreDifferent(this.specifiedName, name)) {
+ this.getColumnAnnotation().setName(name);
+ this.removeColumnAnnotationIfUnset();
+ this.setSpecifiedName_(name);
+ }
+ }
+
+ protected void setSpecifiedName_(String name) {
+ String old = this.specifiedName;
+ this.specifiedName = name;
+ this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildSpecifiedName() {
+ return this.getColumnAnnotation().getName();
+ }
+
+ public String getDefaultName() {
+ return this.defaultName;
+ }
+
+ protected void setDefaultName(String name) {
+ String old = this.defaultName;
+ this.defaultName = name;
+ this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildDefaultName() {
+ return this.owner.getDefaultColumnName();
+ }
+
+
+ // ********** column definition **********
+
+ public String getColumnDefinition() {
+ return this.columnDefinition;
+ }
+
+ public void setColumnDefinition(String columnDefinition) {
+ if (this.valuesAreDifferent(this.columnDefinition, columnDefinition)) {
+ this.getColumnAnnotation().setColumnDefinition(columnDefinition);
+ this.removeColumnAnnotationIfUnset();
+ this.setColumnDefinition_(columnDefinition);
+ }
+ }
+
+ protected void setColumnDefinition_(String columnDefinition) {
+ String old = this.columnDefinition;
+ this.columnDefinition = columnDefinition;
+ this.firePropertyChanged(COLUMN_DEFINITION_PROPERTY, old, columnDefinition);
+ }
+
+ public String buildColumnDefinition() {
+ return this.getColumnAnnotation().getColumnDefinition();
+ }
+
+
+ // ********** database stuff **********
+
+ protected Column getDbColumn() {
+ Table table = this.getDbTable();
+ return (table == null) ? null : table.getColumnForIdentifier(this.getName());
+ }
+
+ public Table getDbTable() {
+ return this.owner.resolveDbTable(this.getTable());
+ }
+
+ /**
+ * Return the name of the column's table. This is overridden
+ * in {@link AbstractJavaBaseColumn} where a table can be defined.
+ */
+ public String getTable() {
+ return this.owner.getTypeMapping().getPrimaryTableName();
+ }
+
+ public boolean isResolved() {
+ return this.getDbColumn() != null;
+ }
+
+
+ // ********** Java completion proposals **********
+
+ @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.nameTouches(pos, astRoot)) {
+ return this.getJavaCandidateNames(filter).iterator();
+ }
+ return null;
+ }
+
+ protected boolean nameTouches(int pos, CompilationUnit astRoot) {
+ return this.getColumnAnnotation().nameTouches(pos, astRoot);
+ }
+
+ protected Iterable<String> getJavaCandidateNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.getCandidateNames(filter));
+ }
+
+ protected Iterable<String> getCandidateNames(Filter<String> filter) {
+ return new FilteringIterable<String>(this.getCandidateNames(), filter);
+ }
+
+ protected Iterable<String> getCandidateNames() {
+ Table dbTable = this.getDbTable();
+ return (dbTable != null) ? dbTable.getSortedColumnIdentifiers() : EmptyIterable.<String> instance();
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.buildColumnValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildColumnValidator(CompilationUnit astRoot) {
+ return this.owner.buildColumnValidator(this, buildTextRangeResolver(astRoot));
+ }
+
+ protected NamedColumnTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaNamedColumnTextRangeResolver(this, astRoot);
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.getColumnAnnotation().getTextRange(astRoot);
+ return (textRange != null) ? textRange : this.owner.getValidationTextRange(astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.getColumnAnnotation().getNameTextRange(astRoot);
+ return (textRange != null) ? textRange : this.owner.getValidationTextRange(astRoot);
+ }
+
+
+ // ********** misc **********
+
+ public boolean isVirtual() {
+ return false;
+ }
+
+ protected void initializeFrom(ReadOnlyNamedColumn oldColumn) {
+ this.setSpecifiedName(oldColumn.getSpecifiedName());
+ this.setColumnDefinition(oldColumn.getColumnDefinition());
+ }
+
+ protected void initializeFromVirtual(ReadOnlyNamedColumn virtualColumn) {
+ this.setSpecifiedName(virtualColumn.getName());
+ this.setColumnDefinition(virtualColumn.getColumnDefinition());
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ String table = this.getTable();
+ if (table != null) {
+ sb.append(table);
+ sb.append('.');
+ }
+ sb.append(this.getName());
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMapping.java
new file mode 100644
index 0000000000..a7614b8d84
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMapping.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappingRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaOneToManyRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.NullJavaOrphanRemoval2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOneToManyMapping2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrphanRemovable2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrphanRemovalHolder2_0;
+import org.eclipse.jpt.jpa.core.resource.java.OneToManyAnnotation;
+
+public abstract class AbstractJavaOneToManyMapping
+ extends AbstractJavaMultiRelationshipMapping<OneToManyAnnotation>
+ implements JavaOneToManyMapping2_0, JavaOrphanRemovalHolder2_0
+{
+ protected final JavaOrphanRemovable2_0 orphanRemoval;
+
+
+ protected AbstractJavaOneToManyMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.orphanRemoval = this.buildOrphanRemoval();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.orphanRemoval.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.orphanRemoval.update();
+ }
+
+
+ // ********** relationship **********
+
+ @Override
+ public JavaOneToManyRelationship getRelationship() {
+ return (JavaOneToManyRelationship) super.getRelationship();
+ }
+
+ @Override
+ protected JavaMappingRelationship buildRelationship() {
+ return new GenericJavaOneToManyRelationship(this, this.isJpa2_0Compatible());
+ }
+
+
+ // ********** orphan removal **********
+
+ public JavaOrphanRemovable2_0 getOrphanRemoval() {
+ return this.orphanRemoval;
+ }
+
+ protected JavaOrphanRemovable2_0 buildOrphanRemoval() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildJavaOrphanRemoval(this) :
+ new NullJavaOrphanRemoval2_0(this);
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.ONE_TO_MANY_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return OneToManyAnnotation.ANNOTATION_NAME;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMappingDefinition.java
new file mode 100644
index 0000000000..fbc1bffffd
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToManyMappingDefinition.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.MapKeyAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.OneToManyAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.OrderByAnnotation;
+
+public abstract class AbstractJavaOneToManyMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaOneToManyMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.ONE_TO_MANY_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return OneToManyAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ JoinTableAnnotation.ANNOTATION_NAME,
+ MapKeyAnnotation.ANNOTATION_NAME,
+ OrderByAnnotation.ANNOTATION_NAME,
+ JoinColumnAnnotation.ANNOTATION_NAME,
+ JoinColumnsAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaOneToManyMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMapping.java
new file mode 100644
index 0000000000..1fca5e88aa
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMapping.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaOneToOneRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.NullJavaOrphanRemoval2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOneToOneMapping2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrphanRemovable2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrphanRemovalHolder2_0;
+import org.eclipse.jpt.jpa.core.resource.java.OneToOneAnnotation;
+
+
+public abstract class AbstractJavaOneToOneMapping
+ extends AbstractJavaSingleRelationshipMapping<OneToOneAnnotation>
+ implements JavaOneToOneMapping2_0, JavaOrphanRemovalHolder2_0
+{
+ protected final JavaOrphanRemovable2_0 orphanRemoval;
+
+
+ protected AbstractJavaOneToOneMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.orphanRemoval = this.buildOrphanRemoval();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.orphanRemoval.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.orphanRemoval.update();
+ }
+
+
+ // ********** relationship **********
+
+ @Override
+ public JavaOneToOneRelationship getRelationship() {
+ return (JavaOneToOneRelationship) super.getRelationship();
+ }
+
+ @Override
+ protected JavaOneToOneRelationship buildRelationship() {
+ return new GenericJavaOneToOneRelationship(this);
+ }
+
+
+ // ********** orphan removal **********
+
+ public JavaOrphanRemovable2_0 getOrphanRemoval() {
+ return this.orphanRemoval;
+ }
+
+ protected JavaOrphanRemovable2_0 buildOrphanRemoval() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildJavaOrphanRemoval(this) :
+ new NullJavaOrphanRemoval2_0(this);
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return OneToOneAnnotation.ANNOTATION_NAME;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMappingDefinition.java
new file mode 100644
index 0000000000..e5df782d91
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOneToOneMappingDefinition.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.OneToOneAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnsAnnotation;
+
+public abstract class AbstractJavaOneToOneMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaOneToOneMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return OneToOneAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ JoinTableAnnotation.ANNOTATION_NAME,
+ JoinColumnAnnotation.ANNOTATION_NAME,
+ JoinColumnsAnnotation.ANNOTATION_NAME,
+ PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME,
+ PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaOneToOneMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOverride.java
new file mode 100644
index 0000000000..f460c8dbfa
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaOverride.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyOverride;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverride;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverride;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
+import org.eclipse.jpt.jpa.core.resource.java.OverrideAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Specified Java override
+ */
+public abstract class AbstractJavaOverride<C extends JavaOverrideContainer, A extends OverrideAnnotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaOverride
+{
+ protected final A overrideAnnotation;
+
+ protected String name;
+
+
+ protected AbstractJavaOverride(C parent, A overrideAnnotation) {
+ super(parent);
+ this.overrideAnnotation = overrideAnnotation;
+ this.name = this.buildName();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setName_(this.buildName());
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Strip the prefix (if necessary) before storing the name in the context
+ * model. Pass the unchanged name to the annotation.
+ */
+ public void setName(String name) {
+ this.overrideAnnotation.setName(name);
+ this.setName_(this.stripPrefix(name));
+ }
+
+ protected void setName_(String name) {
+ String old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+ /**
+ * Strip the prefix (if necessary) from the name taken from the annotation
+ * before storing it in the context model.
+ */
+ protected String buildName() {
+ return this.stripPrefix(this.overrideAnnotation.getName());
+ }
+
+ protected String stripPrefix(String rawName) {
+ if (rawName == null) {
+ return null;
+ }
+ String prefix = this.getPossiblePrefix();
+ if (prefix == null) {
+ return rawName;
+ }
+ int prefixLength = prefix.length();
+ if ((rawName.length() > prefixLength) &&
+ (rawName.charAt(prefixLength) == '.') &&
+ rawName.startsWith(prefix)) {
+ return rawName.substring(prefixLength + 1);
+ }
+ return rawName;
+ }
+
+ protected String getPossiblePrefix() {
+ return this.getContainer().getPossiblePrefix();
+ }
+
+
+ // ********** specified/virtual **********
+
+ public boolean isVirtual() {
+ return false;
+ }
+
+ public JavaVirtualOverride convertToVirtual() {
+ return this.getContainer().convertOverrideToVirtual(this);
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public C getParent() {
+ return (C) super.getParent();
+ }
+
+ public C getContainer() {
+ return this.getParent();
+ }
+
+ public A getOverrideAnnotation() {
+ return this.overrideAnnotation;
+ }
+
+ protected void initializeFrom(ReadOnlyOverride oldOverride) {
+ this.setName(this.prefix(oldOverride.getName()));
+ }
+
+ protected void initializeFromVirtual(ReadOnlyOverride virtualOverride) {
+ this.setName(this.prefix(virtualOverride.getName()));
+ }
+
+ protected String prefix(String oldName) {
+ if (oldName == null) {
+ return null;
+ }
+ String prefix = this.getWritePrefix();
+ return (prefix == null) ? oldName : (prefix + '.' + oldName);
+ }
+
+ protected String getWritePrefix() {
+ return this.getContainer().getWritePrefix();
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.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;
+ }
+ if (this.nameTouches(pos, astRoot)) {
+ return this.javaCandidateNames(filter);
+ }
+ return null;
+ }
+
+ protected boolean nameTouches(int pos, CompilationUnit astRoot) {
+ return this.overrideAnnotation.nameTouches(pos, astRoot);
+ }
+
+ protected Iterator<String> javaCandidateNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.candidateNames(filter));
+ }
+
+ private Iterator<String> candidateNames(Filter<String> filter) {
+ return new FilteringIterator<String>(this.candidateNames(), filter);
+ }
+
+ protected abstract Iterator<String> candidateNames();
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.buildValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildValidator(CompilationUnit astRoot) {
+ return this.getContainer().buildValidator(this, buildTextRangeResolver(astRoot));
+ }
+
+ protected OverrideTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaOverrideTextRangeResolver(this, astRoot);
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.overrideAnnotation.getTextRange(astRoot);
+ return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.overrideAnnotation.getNameTextRange(astRoot);
+ return (textRange != null) ? textRange : this.getValidationTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java
new file mode 100644
index 0000000000..10d11930cd
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentAttribute.java
@@ -0,0 +1,816 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Modifier;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
+import org.eclipse.jpt.common.utility.internal.ClassName;
+import org.eclipse.jpt.common.utility.internal.ReflectionTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.context.AccessType;
+import org.eclipse.jpt.jpa.core.context.CollectionMapping;
+import org.eclipse.jpt.jpa.core.context.Embeddable;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaStructureNodes;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.PersistentAttributeTextRangeResolver;
+import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentAttribute2_0;
+import org.eclipse.jpt.jpa.core.jpa2.resource.java.JPA2_0;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java persistent attributes
+ */
+public abstract class AbstractJavaPersistentAttribute
+ extends AbstractJavaJpaContextNode
+ implements JavaPersistentAttribute2_0
+{
+ protected final JavaResourcePersistentAttribute resourcePersistentAttribute;
+
+ protected String name;
+
+ protected AccessType defaultAccess;
+
+ protected JavaAttributeMapping mapping; // never null
+ protected String defaultMappingKey;
+
+
+ protected AbstractJavaPersistentAttribute(PersistentType parent, JavaResourcePersistentAttribute resourcePersistentAttribute) {
+ super(parent);
+ this.resourcePersistentAttribute = resourcePersistentAttribute;
+ this.name = resourcePersistentAttribute.getName();
+
+ // this is determined directly from the resource model
+ this.defaultAccess = this.buildDefaultAccess();
+
+ // keep non-null at all times
+ this.mapping = this.buildMapping();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setName(this.resourcePersistentAttribute.getName());
+ // this is determined directly from the resource model
+ this.setDefaultAccess(this.buildDefaultAccess());
+ this.syncMapping();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateMapping();
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ protected void setName(String name) {
+ String old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ // ********** access **********
+
+ /**
+ * Subclasses determine the specified access.
+ */
+ public AccessType getAccess() {
+ AccessType access = this.getSpecifiedAccess();
+ return (access != null) ? access : this.defaultAccess;
+ }
+
+ public abstract AccessType getSpecifiedAccess();
+
+ public AccessType getDefaultAccess() {
+ return this.defaultAccess;
+ }
+
+ protected void setDefaultAccess(AccessType access) {
+ AccessType old = this.defaultAccess;
+ this.defaultAccess = access;
+ this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, access);
+ }
+
+ protected AccessType buildDefaultAccess() {
+ return this.resourcePersistentAttribute.isField() ? AccessType.FIELD : AccessType.PROPERTY;
+ }
+
+
+ // ********** mapping **********
+
+ public JavaAttributeMapping getMapping() {
+ return this.mapping;
+ }
+
+ /**
+ * Clients do not set the mapping directly.
+ * @see #setMappingKey(String)
+ */
+ protected void setMapping(JavaAttributeMapping mapping) {
+ JavaAttributeMapping old = this.mapping;
+ this.mapping = mapping;
+ this.firePropertyChanged(MAPPING_PROPERTY, old, mapping);
+ }
+
+ public String getMappingKey() {
+ return this.mapping.getKey();
+ }
+
+ /**
+ * Possible transitions:
+ * <table border>
+ * <th>
+ * <th>null mapping/default<br>
+ * <code>key = null</code>
+ * <th>specified mapping A<br>
+ * <code>key = "A"</code>
+ * <th>specified mapping B<br>
+ * <code>key = "B"</code>
+ * <tr>
+ * <th>[default] null mapping
+ * <td>do nothing
+ * <td>add annotation A<br>
+ * set new mapping A
+ * <td>add annotation B<br>
+ * set new mapping B
+ * <tr>
+ * <th>default mapping A
+ * <td>do nothing
+ * <td>add annotation A<br>
+ * <em>re-use</em> default mapping A
+ * <td>add annotation B<br>
+ * set new mapping B
+ * <tr>
+ * <th>specified mapping A
+ * <td>remove annotation A<br>
+ * set new default or null mapping
+ * <td>do nothing
+ * <td>remove annotation A<br>
+ * add annotation B<br>
+ * set new mapping B
+ * </table>
+ * The "do nothing" transitions are handled in this method.
+ */
+ public JavaAttributeMapping setMappingKey(String key) {
+ if (this.mapping.isDefault()) {
+ if (key == null) {
+ // leave the default mapping unchanged
+ } else {
+ this.setMappingKey_(key); // replace the default mapping
+ }
+ } else {
+ if (this.valuesAreEqual(key, this.mapping.getKey())) {
+ // leave the specified mapping unchanged
+ } else {
+ this.setMappingKey_(key); // replace the specified mapping
+ }
+ }
+ return this.mapping;
+ }
+
+ /**
+ * We have either:<ul>
+ * <li>a <em>default</em> mapping and a non-<code>null</code> key
+ * </ul>or<ul>
+ * <li>a <em>specified</em> mapping and a different (possibly
+ * <code>null</code>) key
+ * </ul>
+ */
+ protected void setMappingKey_(String key) {
+ JavaAttributeMappingDefinition definition = this.getSpecifiedMappingDefinition(key);
+ if (definition == null) {
+ // our mapping is "specified" and the key is null;
+ // check for a default definition
+ definition = this.getDefaultMappingDefinition();
+ Iterable<String> supportingAnnotationNames = (definition != null) ? definition.getSupportingAnnotationNames() : EmptyIterable.<String>instance();
+ // clear any mapping annotation(s);
+ // leave the "default" mapping's supporting annotations;
+ // if there is no "default" mapping, clear all supporting annotations too(?)
+ this.setMappingAnnotation(null, supportingAnnotationNames);
+ } else {
+ this.setMappingAnnotation(definition);
+ }
+ // note: 'definition' can still be null (if the key is null and there is no "default" mapping)
+ this.setMapping(this.buildMapping(definition));
+ }
+
+ /**
+ * pre-condition: definition is not <code>null</code>
+ */
+ protected void setMappingAnnotation(JavaAttributeMappingDefinition definition) {
+ this.setMappingAnnotation(definition.getAnnotationName(), definition.getSupportingAnnotationNames());
+ }
+
+ protected void setMappingAnnotation(String primaryAnnotationName, Iterable<String> supportingAnnotationNames) {
+ this.resourcePersistentAttribute.setPrimaryAnnotation(primaryAnnotationName, supportingAnnotationNames);
+ }
+
+ protected JavaAttributeMapping buildMapping(JavaAttributeMappingDefinition definition) {
+ return (definition == null) ? this.buildNullMapping() : this.buildMapping_(definition);
+ }
+
+ protected JavaAttributeMapping buildNullMapping() {
+ return this.getJpaFactory().buildJavaNullAttributeMapping(this);
+ }
+
+ /**
+ * pre-condition: definition is not null
+ * <p>
+ * If we are converting a <em>default</em> mapping to its <em>specified</em>
+ * manifestation, we just keep the same mapping and create its annotation.
+ * We do <em>not</em> do the same thing when converting a <em>specified</em>
+ * mapping to its <em>default</em> manifestation. We rebuild the
+ * entire mapping, simplifying the clearing of all its state. We do this
+ * because we allow clients to modify a <em>default</em> mapping (or any of
+ * its components) directly,
+ * modifying its state and triggering a conversion to a <em>specified</em>
+ * mapping. The only way to convert a <em>specified</em> mapping to a
+ * <em>default</em> mapping is by {@link #setMappingKey(String) setting the
+ * mapping key} to <code>null</code>.
+ */
+ protected JavaAttributeMapping buildMapping_(JavaAttributeMappingDefinition definition) {
+ // 'mapping' is null during construction
+ if ((this.mapping != null) && this.mapping.isDefault() && Tools.valuesAreEqual(this.mapping.getKey(), definition.getKey())) {
+ this.mapping.updateDefault(); // since nothing here changes, we need to update the mapping's flag
+ return this.mapping;
+ }
+ return definition.buildMapping(this, this.getJpaFactory());
+ }
+
+ /**
+ * We only look for a <em>specified</em> mapping here.
+ * We look for a default mapping during <em>update</em>.
+ */
+ protected JavaAttributeMapping buildMapping() {
+ return this.buildMapping(this.getSpecifiedMappingDefinition());
+ }
+
+ /**
+ * Look for a <em>specified</em> mapping and sync our mapping.
+ */
+ protected void syncMapping() {
+ JavaAttributeMappingDefinition definition = this.getSpecifiedMappingDefinition();
+ if (definition == null) {
+ if (this.mapping.isDefault()) {
+ // null/default => null/default
+ this.mapping.synchronizeWithResourceModel();
+ } else {
+ // specified => null/default
+ definition = this.getDefaultMappingDefinition();
+ this.setMapping(this.buildMapping(definition));
+ }
+ } else {
+ if (this.mapping.isDefault()) {
+ // null/default => specified
+ this.setMapping(this.buildMapping(definition));
+ } else {
+ // specified => specified
+ if (this.valuesAreEqual(definition.getKey(), this.mapping.getKey())) {
+ this.mapping.synchronizeWithResourceModel();
+ } else {
+ this.setMapping(this.buildMapping(definition));
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the "specified" mapping definition for the specified key.
+ */
+ protected JavaAttributeMappingDefinition getSpecifiedMappingDefinition(String key) {
+ if (key == null) {
+ return null;
+ }
+ for (JavaAttributeMappingDefinition definition : this.getSpecifiedMappingDefinitions()) {
+ if (Tools.valuesAreEqual(definition.getKey(), key)) {
+ return definition;
+ }
+ }
+ throw new IllegalArgumentException("invalid mapping key: " + key); //$NON-NLS-1$
+ }
+
+ /**
+ * Return the mapping definition for the mapping currently specified in the
+ * source code.
+ */
+ protected JavaAttributeMappingDefinition getSpecifiedMappingDefinition() {
+ for (JavaAttributeMappingDefinition definition : this.getSpecifiedMappingDefinitions()) {
+ if (definition.isSpecified(this)) {
+ return definition;
+ }
+ }
+ return null;
+ }
+
+ protected Iterable<JavaAttributeMappingDefinition> getSpecifiedMappingDefinitions() {
+ return this.getJpaPlatform().getSpecifiedJavaAttributeMappingDefinitions();
+ }
+
+
+ // ********** default mapping **********
+
+ public String getDefaultMappingKey() {
+ return this.defaultMappingKey;
+ }
+
+ protected void setDefaultMappingKey(String mappingKey) {
+ String old = this.defaultMappingKey;
+ this.defaultMappingKey = mappingKey;
+ this.firePropertyChanged(DEFAULT_MAPPING_KEY_PROPERTY, old, mappingKey);
+ }
+
+ /**
+ * If a mapping annotation is specified, we would have already set a
+ * <em>specified</em> mapping in {@link #syncMapping()}. We need only check
+ * for changes to the <em>default</em> mapping.
+ */
+ protected void updateMapping() {
+ JavaAttributeMappingDefinition definition = this.getDefaultMappingDefinition();
+ String newDefaultKey = (definition == null) ? null : definition.getKey();
+ if (this.mapping.isDefault() && Tools.valuesAreDifferent(this.mapping.getKey(), newDefaultKey)) {
+ this.setMapping(this.buildMapping(definition)); // the default mapping has changed
+ } else {
+ this.mapping.update();
+ }
+ this.setDefaultMappingKey(newDefaultKey);
+ }
+
+ protected JavaAttributeMappingDefinition getDefaultMappingDefinition() {
+ for (DefaultJavaAttributeMappingDefinition definition : this.getDefaultMappingDefinitions()) {
+ if (definition.isDefault(this)) {
+ return definition;
+ }
+ }
+ return null;
+ }
+
+ protected Iterable<DefaultJavaAttributeMappingDefinition> getDefaultMappingDefinitions() {
+ return this.getJpaPlatform().getDefaultJavaAttributeMappingDefinitions();
+ }
+
+
+ // ********** JpaStructureNode implementation **********
+
+ public String getId() {
+ return JavaStructureNodes.PERSISTENT_ATTRIBUTE_ID;
+ }
+
+ public JpaStructureNode getStructureNode(int textOffset) {
+ return this;
+ }
+
+ public TextRange getSelectionTextRange() {
+ return this.getSelectionTextRange(this.buildASTRoot());
+ }
+
+ protected TextRange getSelectionTextRange(CompilationUnit astRoot) {
+ return this.resourcePersistentAttribute.getNameTextRange(astRoot);
+ }
+
+ protected CompilationUnit buildASTRoot() {
+ return this.resourcePersistentAttribute.getJavaResourceCompilationUnit().buildASTRoot();
+ }
+
+ public void dispose() {
+ // nothing to dispose
+ }
+
+
+ // ********** type **********
+
+ /**
+ * From the JPA spec, when the basic mapping applies:<br>
+ * If the type of the attribute (field or property) is one of the following
+ * it must be mapped as <code>@javax.persistence.Basic</code>:<ul>
+ * <li><code>byte[]</code>
+ * <li><code>java.lang.Byte[]</code>
+ * <li><code>char[]</code>
+ * <li><code>java.lang.Character[]</code>
+ * <li>primitive types (except <code>void</code>)
+ * <li>primitive wrappers (except <code>java.lang.Void</code>)
+ * <li><code>java.lang.String</code>
+ * <li><code>java.math.BigInteger</code>
+ * <li><code>java.math.BigDecimal</code>
+ * <li><code>java.util.Date</code>
+ * <li><code>java.util.Calendar</code>
+ * <li><code>java.sql.Date</code>
+ * <li><code>java.sql.Time</code>
+ * <li><code>java.sql.Timestamp</code>
+ * <li><code>enum</code>s
+ * <li>any other type that implements <code>java.io.Serializable</code>
+ * </ul>
+ */
+ public boolean typeIsBasic() {
+ // 'typeName' may include array brackets but not generic type arguments
+ String typeName = this.getTypeName();
+ if (typeName == null) {
+ return false;
+ }
+
+ int arrayDepth = ReflectionTools.getArrayDepthForTypeDeclaration(typeName);
+ if (arrayDepth > 1) {
+ return false; // multi-dimensional arrays are not supported
+ }
+
+ if (arrayDepth == 1) {
+ String elementTypeName = ReflectionTools.getElementTypeNameForTypeDeclaration(typeName, 1);
+ return this.elementTypeIsValidForBasicArray(elementTypeName);
+ }
+
+ // arrayDepth == 0
+ if (ClassName.isVariablePrimitive(typeName)) {
+ return true; // any primitive but 'void'
+ }
+ if (ClassName.isVariablePrimitiveWrapper(typeName)) {
+ return true; // any primitive wrapper but 'java.lang.Void'
+ }
+ if (this.typeIsOtherValidBasicType(typeName)) {
+ return true;
+ }
+ if (this.resourcePersistentAttribute.typeIsEnum()) {
+ return true;
+ }
+ if (this.resourcePersistentAttribute.typeIsSubTypeOf(SERIALIZABLE_TYPE_NAME)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return whether the specified type is a valid element type for
+ * a one-dimensional array that can default to a basic mapping:<ul>
+ * <li><code>byte</code>
+ * <li><code>java.lang.Byte</code>
+ * <li><code>char</code>
+ * <li><code>java.lang.Character</code>
+ * </ul>
+ */
+ protected boolean elementTypeIsValidForBasicArray(String elementTypeName) {
+ return ArrayTools.contains(VALID_BASIC_ARRAY_ELEMENT_TYPE_NAMES, elementTypeName);
+ }
+
+ protected static final String[] VALID_BASIC_ARRAY_ELEMENT_TYPE_NAMES = {
+ byte.class.getName(),
+ char.class.getName(),
+ java.lang.Byte.class.getName(),
+ java.lang.Character.class.getName()
+ };
+
+ /**
+ * Return whether the specified type is among the various "other" types
+ * that can default to a basic mapping.
+ */
+ protected boolean typeIsOtherValidBasicType(String typeName) {
+ return ArrayTools.contains(OTHER_VALID_BASIC_TYPE_NAMES, typeName);
+ }
+
+ protected static final String[] OTHER_VALID_BASIC_TYPE_NAMES = {
+ java.lang.String.class.getName(),
+ java.math.BigInteger.class.getName(),
+ java.math.BigDecimal.class.getName(),
+ java.util.Date.class.getName(),
+ java.util.Calendar.class.getName(),
+ java.sql.Date.class.getName(),
+ java.sql.Time.class.getName(),
+ java.sql.Timestamp.class.getName(),
+ };
+
+ protected static final String SERIALIZABLE_TYPE_NAME = java.io.Serializable.class.getName();
+
+ public String getSingleReferenceTargetTypeName() {
+ // 'typeName' may include array brackets ("[]")
+ // but not generic type arguments (e.g. "<java.lang.String>")
+ String typeName = this.getTypeName();
+ if (typeName == null) {
+ return null;
+ }
+ if (ReflectionTools.getArrayDepthForTypeDeclaration(typeName) != 0) {
+ return null; // arrays cannot be entities
+ }
+ if (this.typeIsContainer(typeName)) {
+ return null; // "containers" cannot be entities
+ }
+ return typeName;
+ }
+
+ public String getMultiReferenceTargetTypeName() {
+ return this.getJpaContainerDefinition().getMultiReferenceTargetTypeName(this.resourcePersistentAttribute);
+ }
+
+ public String getMultiReferenceMapKeyTypeName() {
+ return this.getJpaContainerDefinition().getMultiReferenceMapKeyTypeName(this.resourcePersistentAttribute);
+ }
+
+ /**
+ * return whether the specified type is one of the container
+ * types allowed by the JPA spec
+ */
+ protected boolean typeIsContainer(String typeName) {
+ return this.getJpaContainerDefinition(typeName).isContainer();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public PersistentType getParent() {
+ return (PersistentType) super.getParent();
+ }
+
+ public PersistentType getOwningPersistentType() {
+ return this.getParent();
+ }
+
+ public TypeMapping getOwningTypeMapping() {
+ return this.getOwningPersistentType().getMapping();
+ }
+
+ public JavaPersistentAttribute getJavaPersistentAttribute() {
+ return this;
+ }
+
+ public JavaResourcePersistentAttribute getResourcePersistentAttribute() {
+ return this.resourcePersistentAttribute;
+ }
+
+ public String getPrimaryKeyColumnName() {
+ return this.getMapping().getPrimaryKeyColumnName();
+ }
+
+ public String getTypeName() {
+ return this.resourcePersistentAttribute.getTypeName();
+ }
+
+ /**
+ * Java attributes always correspond to attributes in the source code.
+ */
+ public boolean isVirtual() {
+ return false;
+ }
+
+ public boolean contains(int offset, CompilationUnit astRoot) {
+ TextRange fullTextRange = this.getFullTextRange(astRoot);
+ // 'fullTextRange' will be null if the attribute no longer exists in the java;
+ // the context model can be out of synch with the resource model
+ // when a selection event occurs before the context model has a
+ // chance to synch with the resource model via the update thread
+ return (fullTextRange == null) ? false : fullTextRange.includes(offset);
+ }
+
+ protected TextRange getFullTextRange(CompilationUnit astRoot) {
+ return this.resourcePersistentAttribute.getTextRange(astRoot);
+ }
+
+ public Embeddable getEmbeddable() {
+ String typeName = this.getTypeName();
+ return (typeName == null) ? null : this.getPersistenceUnit().getEmbeddable(typeName);
+ }
+
+ public boolean isField() {
+ return this.resourcePersistentAttribute.isField();
+ }
+
+ public boolean isProperty() {
+ return this.resourcePersistentAttribute.isProperty();
+ }
+
+ public boolean isPublic() {
+ return Modifier.isPublic(this.resourcePersistentAttribute.getModifiers());
+ }
+
+ public boolean isFinal() {
+ return Modifier.isFinal(this.resourcePersistentAttribute.getModifiers());
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.name);
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getSelectionTextRange(astRoot);
+ }
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+
+ this.validateAttribute(messages, reporter, astRoot);
+
+ this.getMapping().validate(messages, reporter, astRoot);
+ }
+
+ protected void validateAttribute(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.buildAttibuteValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected abstract JptValidator buildAttibuteValidator(CompilationUnit astRoot);
+
+ protected PersistentAttributeTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaPersistentAttributeTextRangeResolver(this, astRoot);
+ }
+
+
+ // ********** 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;
+ }
+ return this.getMapping().javaCompletionProposals(pos, filter, astRoot);
+ }
+
+
+ // ********** metamodel **********
+
+ public String getMetamodelContainerFieldTypeName() {
+ return this.getJpaContainerDefinition().getMetamodelContainerFieldTypeName();
+ }
+
+ public String getMetamodelContainerFieldMapKeyTypeName() {
+ return this.getJpaContainerDefinition().getMetamodelContainerFieldMapKeyTypeName((CollectionMapping) this.getMapping());
+ }
+
+ public String getMetamodelTypeName() {
+ String typeName = this.getTypeName();
+ if (typeName == null) {
+ return MetamodelField.DEFAULT_TYPE_NAME;
+ }
+ if (ClassName.isPrimitive(typeName)) {
+ return ClassName.getWrapperClassName(typeName); // ???
+ }
+ return typeName;
+ }
+
+
+ // ********** JPA container definition **********
+
+ public JpaContainerDefinition getJpaContainerDefinition() {
+ // 'typeName' may include array brackets ("[]")
+ // but not generic type arguments (e.g. "<java.lang.String>")
+ return this.getJpaContainerDefinition(this.resourcePersistentAttribute.getTypeName());
+ }
+
+ /**
+ * Return the JPA container definition corresponding to the specified type;
+ * return a "null" definition if the specified type is not one of the
+ * container types allowed by the JPA spec.
+ */
+ protected JpaContainerDefinition getJpaContainerDefinition(String typeName) {
+ for (JpaContainerDefinition definition : this.getJpaContainerDefinitions()) {
+ if (definition.getTypeName().equals(typeName)) {
+ return definition;
+ }
+ }
+ return JpaContainerDefinition.Null.instance();
+ }
+
+ protected Iterable<JpaContainerDefinition> getJpaContainerDefinitions() {
+ return JPA_CONTAINER_DEFINITIONS;
+ }
+
+ protected static final JpaContainerDefinition[] JPA_CONTAINER_DEFINITION_ARRAY = new JpaContainerDefinition[] {
+ new CollectionJpaContainerDefinition(java.util.Collection.class, JPA2_0.COLLECTION_ATTRIBUTE),
+ new CollectionJpaContainerDefinition(java.util.Set.class, JPA2_0.SET_ATTRIBUTE),
+ new CollectionJpaContainerDefinition(java.util.List.class, JPA2_0.LIST_ATTRIBUTE),
+ new MapJpaContainerDefinition(java.util.Map.class, JPA2_0.MAP_ATTRIBUTE)
+ };
+
+ protected static final Iterable<JpaContainerDefinition> JPA_CONTAINER_DEFINITIONS = new ArrayIterable<JpaContainerDefinition>(JPA_CONTAINER_DEFINITION_ARRAY);
+
+
+ /**
+ * Abstract JPA container definition
+ */
+ protected abstract static class AbstractJpaContainerDefinition
+ implements JpaContainerDefinition
+ {
+ protected final String typeName;
+ protected final String metamodelContainerFieldTypeName;
+
+ protected AbstractJpaContainerDefinition(Class<?> containerClass, String metamodelContainerFieldTypeName) {
+ this(containerClass.getName(), metamodelContainerFieldTypeName);
+ }
+
+ protected AbstractJpaContainerDefinition(String typeName, String metamodelContainerFieldTypeName) {
+ super();
+ if ((typeName == null) || (metamodelContainerFieldTypeName == null)) {
+ throw new NullPointerException();
+ }
+ this.typeName = typeName;
+ this.metamodelContainerFieldTypeName = metamodelContainerFieldTypeName;
+ }
+
+ public String getTypeName() {
+ return this.typeName;
+ }
+
+ public boolean isContainer() {
+ return true;
+ }
+
+ public String getMetamodelContainerFieldTypeName() {
+ return this.metamodelContainerFieldTypeName;
+ }
+
+ }
+
+ /**
+ * Collection JPA container definition
+ */
+ protected static class CollectionJpaContainerDefinition
+ extends AbstractJpaContainerDefinition
+ {
+ protected CollectionJpaContainerDefinition(Class<?> collectionClass, String staticMetamodelTypeDeclarationTypeName) {
+ super(collectionClass, staticMetamodelTypeDeclarationTypeName);
+ }
+
+ public String getMultiReferenceTargetTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
+ return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 1) ?
+ resourcePersistentAttribute.getTypeTypeArgumentName(0) :
+ null;
+ }
+
+ public String getMultiReferenceMapKeyTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
+ return null;
+ }
+
+ public String getMetamodelContainerFieldMapKeyTypeName(CollectionMapping mapping) {
+ return null;
+ }
+
+ public boolean isMap() {
+ return false;
+ }
+ }
+
+ /**
+ * Map JPA container definition
+ */
+ protected static class MapJpaContainerDefinition
+ extends AbstractJpaContainerDefinition
+ {
+ protected MapJpaContainerDefinition(Class<?> mapClass, String staticMetamodelTypeDeclarationTypeName) {
+ super(mapClass, staticMetamodelTypeDeclarationTypeName);
+ }
+
+ public String getMultiReferenceTargetTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
+ return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 2) ?
+ resourcePersistentAttribute.getTypeTypeArgumentName(1) :
+ null;
+ }
+
+ public String getMultiReferenceMapKeyTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
+ return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 2) ?
+ resourcePersistentAttribute.getTypeTypeArgumentName(0) :
+ null;
+ }
+
+ public String getMetamodelContainerFieldMapKeyTypeName(CollectionMapping mapping) {
+ return mapping.getMetamodelFieldMapKeyTypeName();
+ }
+
+ public boolean isMap() {
+ return true;
+ }
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java
new file mode 100644
index 0000000000..3891dcca22
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaPersistentType.java
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Vector;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.ClassName;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterables.ChainIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SnapshotCloneIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.jpa.core.JpaFile;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.jpt.jpa.core.context.AccessType;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaStructureNodes;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMappingDefinition;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.resource.java.source.SourceNode;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
+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;
+
+/**
+ * Java persistent type:<ul>
+ * <li>name
+ * <li>access
+ * <li>mapping
+ * <li>attributes
+ * <li>super persistent type
+ * </ul>
+ */
+public abstract class AbstractJavaPersistentType
+ extends AbstractJavaJpaContextNode
+ implements JavaPersistentType
+{
+ protected final JavaResourcePersistentType resourcePersistentType;
+
+ protected String name;
+
+ protected PersistentType superPersistentType;
+
+ protected AccessType specifiedAccess;
+ protected AccessType defaultAccess; // never null
+
+ protected JavaTypeMapping mapping; // never null
+
+ protected final Vector<JavaPersistentAttribute> attributes = new Vector<JavaPersistentAttribute>();
+ protected final AttributeContainerAdapter attributeContainerAdapter = new AttributeContainerAdapter();
+
+
+ protected AbstractJavaPersistentType(PersistentType.Owner parent, JavaResourcePersistentType resourcePersistentType) {
+ super(parent);
+ this.resourcePersistentType = resourcePersistentType;
+ this.name = resourcePersistentType.getQualifiedName();
+ this.specifiedAccess = this.buildSpecifiedAccess();
+
+ // keep this non-null
+ this.defaultAccess = AccessType.FIELD;
+
+ this.mapping = this.buildMapping();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setName(this.resourcePersistentType.getQualifiedName());
+ this.setSpecifiedAccess_(this.buildSpecifiedAccess());
+ this.syncMapping();
+ this.synchronizeNodesWithResourceModel(this.getAttributes());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setSuperPersistentType(this.buildSuperPersistentType());
+ this.setDefaultAccess(this.buildDefaultAccess());
+ this.mapping.update();
+ this.updateAttributes();
+ this.registerRootStructureNode();
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getSimpleName(){
+ return ClassName.getSimpleName(this.name);
+ }
+
+ protected void setName(String name) {
+ String old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ // ********** 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 PersistentType buildSuperPersistentType() {
+ HashSet<JavaResourcePersistentType> visited = new HashSet<JavaResourcePersistentType>();
+ visited.add(this.resourcePersistentType);
+ PersistentType spt = this.resolveSuperPersistentType(this.resourcePersistentType.getSuperclassQualifiedName(), visited);
+ if (spt == null) {
+ return null;
+ }
+ if (CollectionTools.contains(spt.inheritanceHierarchy(), this)) {
+ return null; // short-circuit in this case, we have circular inheritance
+ }
+ return spt.isMapped() ? spt : spt.getSuperPersistentType();
+ }
+
+ /**
+ * The JPA spec allows non-persistent types in a persistent type's
+ * inheritance hierarchy. We check for a persistent type with the
+ * specified name in the persistence unit. If it is not found we use
+ * resource persistent type and look for <em>its</em> super type.
+ * <p>
+ * The <code>visited</code> collection is used to detect a cycle in the
+ * <em>resource</em> type inheritance hierarchy and prevent the resulting
+ * stack overflow. Any cycles in the <em>context</em> type inheritance
+ * hierarchy are handled in {@link #buildSuperPersistentType()}.
+ */
+ protected PersistentType resolveSuperPersistentType(String typeName, Collection<JavaResourcePersistentType> visited) {
+ if (typeName == null) {
+ return null;
+ }
+ JavaResourcePersistentType resourceType = this.getJpaProject().getJavaResourcePersistentType(typeName);
+ if ((resourceType == null) || visited.contains(resourceType)) {
+ return null;
+ }
+ visited.add(resourceType);
+ PersistentType spt = this.resolvePersistentType(typeName);
+ return (spt != null) ? spt : this.resolveSuperPersistentType(resourceType.getSuperclassQualifiedName(), visited); // recurse
+ }
+
+ protected PersistentType resolvePersistentType(String typeName) {
+ return this.getPersistenceUnit().getPersistentType(typeName);
+ }
+
+
+ // ********** access **********
+
+ public AccessType getAccess() {
+ return (this.specifiedAccess != null) ? this.specifiedAccess : this.defaultAccess;
+ }
+
+ public AccessType getSpecifiedAccess() {
+ return this.specifiedAccess;
+ }
+
+ protected void setSpecifiedAccess_(AccessType access) {
+ AccessType old = this.specifiedAccess;
+ this.specifiedAccess = access;
+ this.firePropertyChanged(SPECIFIED_ACCESS_PROPERTY, old, access);
+ }
+
+ /**
+ * Build an access type based on annotations from the resource model.
+ * (This is JPA platform-dependent.)
+ */
+ protected abstract AccessType buildSpecifiedAccess();
+
+ public AccessType getDefaultAccess() {
+ return this.defaultAccess;
+ }
+
+ protected void setDefaultAccess(AccessType access) {
+ AccessType old = this.defaultAccess;
+ this.defaultAccess = access;
+ this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, access);
+ }
+
+ /**
+ * Check the access "specified" by the Java resource model:<ul>
+ * <li>Check Java annotations first
+ * <li>If <code>null</code>, check XML mapping specified access
+ * <li>If still <code>null</code>, check {@link #superPersistentType} access
+ * <li>If still <code>null</code>, check <code>entity-mappings</code>
+ * specified access setting if the corresponding <code>persistent-type</code>
+ * is listed in a mapping (<code>orm.xml</code>) file
+ * <li>If still <code>null</code>, check the <code>persistence-unit</code>
+ * default Access
+ * <li>Default to {@link AccessType#FIELD FIELD} if all else fails.
+ * </ul>
+ */
+ protected AccessType buildDefaultAccess() {
+ AccessType accessType = AccessType.fromJavaResourceModel(JavaResourcePersistentType.Tools.buildAccess(this.resourcePersistentType));
+ if (accessType != null) {
+ return accessType;
+ }
+ accessType = this.getOwnerOverrideAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+
+ if (this.superPersistentType != null) {
+ accessType = this.superPersistentType.getAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+ }
+
+ accessType = this.getOwnerDefaultAccess();
+ if (accessType != null) {
+ return accessType;
+ }
+
+ // last ditch attempt to allow the user to annotate *something*
+ return AccessType.FIELD;
+ }
+
+
+ // ********** mapping **********
+
+ public JavaTypeMapping getMapping() {
+ return this.mapping;
+ }
+
+ public String getMappingKey() {
+ return this.mapping.getKey();
+ }
+
+ public void setMappingKey(String key) {
+ if (this.valuesAreDifferent(key, this.getMappingKey())) {
+ this.setMapping(this.buildMapping(key));
+ }
+ }
+
+ protected JavaTypeMapping buildMapping(String key) {
+ for (JavaTypeMappingDefinition definition : this.getMappingDefinitions()) {
+ if (Tools.valuesAreEqual(definition.getKey(), key)) {
+ Annotation annotation = this.resourcePersistentType.setPrimaryAnnotation(definition.getAnnotationName(), definition.getSupportingAnnotationNames());
+ return definition.buildMapping(this, annotation, this.getJpaFactory());
+ }
+ }
+ this.resourcePersistentType.setPrimaryAnnotation(null, EmptyIterable.<String>instance());
+ return this.buildNullMapping();
+ }
+
+ /**
+ * Clients do not set the mapping directly.
+ * @see #setMappingKey(String)
+ */
+ protected void setMapping(JavaTypeMapping mapping) {
+ JavaTypeMapping old = this.mapping;
+ this.mapping = mapping;
+ this.firePropertyChanged(MAPPING_PROPERTY, old, mapping);
+ }
+
+ protected JavaTypeMapping buildMapping() {
+ for (JavaTypeMappingDefinition definition : this.getMappingDefinitions()) {
+ Annotation annotation = this.resourcePersistentType.getAnnotation(definition.getAnnotationName());
+ if (annotation != null) {
+ return definition.buildMapping(this, annotation, this.getJpaFactory());
+ }
+ }
+ return this.buildNullMapping();
+ }
+
+ protected void syncMapping() {
+ JavaTypeMappingDefinition definition = null;
+ Annotation annotation = null;
+ for (Iterator<JavaTypeMappingDefinition> stream = this.mappingDefinitions(); stream.hasNext(); ) {
+ definition = stream.next();
+ annotation = this.resourcePersistentType.getAnnotation(definition.getAnnotationName());
+ if (annotation != null) {
+ break;
+ }
+ }
+ // 'annotation' can still be null when we get here
+ if (this.mapping.getMappingAnnotation() == annotation) {
+ this.mapping.synchronizeWithResourceModel();
+ } else {
+ this.setMapping(this.buildMapping(annotation, definition));
+ }
+ }
+
+ protected JavaTypeMapping buildMapping(Annotation annotation, JavaTypeMappingDefinition definition) {
+ return (annotation != null) ?
+ definition.buildMapping(this, annotation, this.getJpaFactory()) :
+ this.buildNullMapping();
+ }
+
+ protected Iterator<JavaTypeMappingDefinition> mappingDefinitions() {
+ return this.getMappingDefinitions().iterator();
+ }
+
+ protected Iterable<JavaTypeMappingDefinition> getMappingDefinitions() {
+ return this.getJpaPlatform().getJavaTypeMappingDefinitions();
+ }
+
+ protected JavaTypeMapping buildNullMapping() {
+ return this.getJpaFactory().buildJavaNullTypeMapping(this);
+ }
+
+ public boolean isMapped() {
+ return this.mapping.isMapped();
+ }
+
+
+ // ********** attributes **********
+
+ public ListIterator<JavaPersistentAttribute> attributes() {
+ return this.getAttributes().iterator();
+ }
+
+ protected ListIterable<JavaPersistentAttribute> getAttributes() {
+ return new LiveCloneListIterable<JavaPersistentAttribute>(this.attributes);
+ }
+
+ public int attributesSize() {
+ return this.attributes.size();
+ }
+
+ public Iterator<String> attributeNames() {
+ return this.getAttributeNames().iterator();
+ }
+
+ protected Iterable<String> getAttributeNames() {
+ return this.convertToNames(this.getAttributes());
+ }
+
+ public JavaPersistentAttribute getAttributeNamed(String attributeName) {
+ Iterator<JavaPersistentAttribute> stream = this.getAttributesNamed(attributeName).iterator();
+ return stream.hasNext() ? stream.next() : null;
+ }
+
+ public JavaPersistentAttribute getAttributeFor(JavaResourcePersistentAttribute javaResourceAttribute) {
+ for (JavaPersistentAttribute javaAttribute : this.getAttributes()) {
+ if (javaAttribute.getResourcePersistentAttribute() == javaResourceAttribute) {
+ return javaAttribute;
+ }
+ }
+ return null;
+ }
+
+ public Iterator<ReadOnlyPersistentAttribute> allAttributes() {
+ return this.getAllAttributes().iterator();
+ }
+
+ protected Iterable<ReadOnlyPersistentAttribute> getAllAttributes() {
+ return new CompositeIterable<ReadOnlyPersistentAttribute>(
+ new TransformationIterable<PersistentType, Iterable<ReadOnlyPersistentAttribute>>(this.getInheritanceHierarchy()) {
+ @Override
+ protected Iterable<ReadOnlyPersistentAttribute> transform(PersistentType pt) {
+ return new SnapshotCloneIterable<ReadOnlyPersistentAttribute>(pt.attributes());
+ }
+ }
+ );
+ }
+
+ public Iterator<String> allAttributeNames() {
+ return this.getAllAttributeNames().iterator();
+ }
+
+ protected Iterable<String> getAllAttributeNames() {
+ return this.convertToNames(this.getAllAttributes());
+ }
+
+ protected Iterable<JavaPersistentAttribute> getAttributesNamed(final String attributeName) {
+ return new FilteringIterable<JavaPersistentAttribute>(this.getAttributes()) {
+ @Override
+ protected boolean accept(JavaPersistentAttribute attribute) {
+ return Tools.valuesAreEqual(attributeName, attribute.getName());
+ }
+ };
+ }
+
+ public ReadOnlyPersistentAttribute resolveAttribute(String attributeName) {
+ Iterator<JavaPersistentAttribute> stream = this.getAttributesNamed(attributeName).iterator();
+ if (stream.hasNext()) {
+ JavaPersistentAttribute attribute = stream.next();
+ // return null if we have more than one
+ return stream.hasNext() ? null : attribute;
+ }
+ // recurse
+ return (this.superPersistentType == null) ? null : this.superPersistentType.resolveAttribute(attributeName);
+ }
+
+ protected Iterable<String> convertToNames(Iterable<? extends ReadOnlyPersistentAttribute> attrs) {
+ return new TransformationIterable<ReadOnlyPersistentAttribute, String>(attrs) {
+ @Override
+ protected String transform(ReadOnlyPersistentAttribute attribute) {
+ return attribute.getName();
+ }
+ };
+ }
+
+ protected Iterator<JavaResourcePersistentAttribute> resourceAttributes() {
+ return (this.getAccess() == AccessType.PROPERTY) ?
+ this.resourcePersistentType.persistableProperties() :
+ this.resourcePersistentType.persistableFields();
+ }
+
+ protected Iterable<JavaResourcePersistentAttribute> getResourceAttributes() {
+ return CollectionTools.iterable(this.resourceAttributes());
+ }
+
+ protected JavaPersistentAttribute buildAttribute(JavaResourcePersistentAttribute resourceAttribute) {
+ return this.getJpaFactory().buildJavaPersistentAttribute(this, resourceAttribute);
+ }
+
+ public boolean hasAnyAnnotatedAttributes() {
+ return this.resourcePersistentType.hasAnyAnnotatedAttributes();
+ }
+
+ /**
+ * The attributes are synchronized during the <em>update</em> because
+ * the list of resource attributes is determined by the access type
+ * which can be controlled in a number of different places....
+ */
+ protected void updateAttributes() {
+ ContextContainerTools.update(this.attributeContainerAdapter);
+ }
+
+ protected void moveAttribute(int index, JavaPersistentAttribute attribute) {
+ this.moveItemInList(index, attribute, this.attributes, ATTRIBUTES_LIST);
+ }
+
+ protected void addAttribute(int index, JavaResourcePersistentAttribute resourceAttribute) {
+ this.addItemToList(index, this.buildAttribute(resourceAttribute), this.attributes, ATTRIBUTES_LIST);
+ }
+
+ protected void removeAttribute(JavaPersistentAttribute attribute) {
+ this.removeItemFromList(attribute, this.attributes, ATTRIBUTES_LIST);
+ }
+
+ /**
+ * attribute container adapter
+ */
+ protected class AttributeContainerAdapter
+ implements ContextContainerTools.Adapter<JavaPersistentAttribute, JavaResourcePersistentAttribute>
+ {
+ public Iterable<JavaPersistentAttribute> getContextElements() {
+ return AbstractJavaPersistentType.this.getAttributes();
+ }
+ public Iterable<JavaResourcePersistentAttribute> getResourceElements() {
+ return AbstractJavaPersistentType.this.getResourceAttributes();
+ }
+ public JavaResourcePersistentAttribute getResourceElement(JavaPersistentAttribute contextElement) {
+ return contextElement.getResourcePersistentAttribute();
+ }
+ public void moveContextElement(int index, JavaPersistentAttribute element) {
+ AbstractJavaPersistentType.this.moveAttribute(index, element);
+ }
+ public void addContextElement(int index, JavaResourcePersistentAttribute resourceElement) {
+ AbstractJavaPersistentType.this.addAttribute(index, resourceElement);
+ }
+ public void removeContextElement(JavaPersistentAttribute element) {
+ AbstractJavaPersistentType.this.removeAttribute(element);
+ }
+ }
+
+
+ // ********** inheritance **********
+
+ public Iterator<PersistentType> inheritanceHierarchy() {
+ return this.getInheritanceHierarchy().iterator();
+ }
+
+ public Iterable<PersistentType> getInheritanceHierarchy() {
+ return this.getInheritanceHierarchyOf(this);
+ }
+
+ public Iterator<PersistentType> ancestors() {
+ return this.getAncestors().iterator();
+ }
+
+ public Iterable<PersistentType> getAncestors() {
+ return this.getInheritanceHierarchyOf(this.superPersistentType);
+ }
+
+ protected Iterable<PersistentType> getInheritanceHierarchyOf(PersistentType start) {
+ // using a chain iterable to traverse up the inheritance tree
+ return new ChainIterable<PersistentType>(start) {
+ @Override
+ protected PersistentType nextLink(PersistentType persistentType) {
+ return persistentType.getSuperPersistentType();
+ }
+ };
+ }
+
+
+ // ********** JpaStructureNode implementation **********
+
+ public String getId() {
+ return JavaStructureNodes.PERSISTENT_TYPE_ID;
+ }
+
+ // it would be nice if the we passed in an astRoot here, but then we
+ // would need to pass it to the XML structure nodes too...
+ public JpaStructureNode getStructureNode(int offset) {
+ CompilationUnit astRoot = this.buildASTRoot();
+
+ if (this.contains(offset, astRoot)) {
+ for (JavaPersistentAttribute persistentAttribute : this.getAttributes()) {
+ if (persistentAttribute.contains(offset, astRoot)) {
+ return persistentAttribute;
+ }
+ }
+ return this;
+ }
+ return null;
+ }
+
+ protected boolean contains(int offset, CompilationUnit astRoot) {
+ TextRange fullTextRange = this.getFullTextRange(astRoot);
+ // 'fullTextRange' will be null if the type no longer exists in the java;
+ // the context model can be out of synch with the resource model
+ // when a selection event occurs before the context model has a
+ // chance to synch with the resource model via the update thread
+ return (fullTextRange == null) ? false : fullTextRange.includes(offset);
+ }
+
+ protected TextRange getFullTextRange(CompilationUnit astRoot) {
+ return this.resourcePersistentType.getTextRange(astRoot);
+ }
+
+ public TextRange getSelectionTextRange() {
+ return this.getSelectionTextRange(this.buildASTRoot());
+ }
+
+ protected TextRange getSelectionTextRange(CompilationUnit astRoot) {
+ return this.resourcePersistentType.getNameTextRange(astRoot);
+ }
+
+ public void dispose() {
+ this.unregisterRootStructureNode();
+ }
+
+ protected void registerRootStructureNode() {
+ JpaFile jpaFile = this.getJpaFile();
+ // the JPA file can be null if the resource type is "external"
+ if (jpaFile != null) {
+ jpaFile.addRootStructureNode(this.name, this);
+ }
+ }
+
+ protected void unregisterRootStructureNode() {
+ JpaFile jpaFile = this.getJpaFile();
+ // the JPA file can be null if the .java file was deleted
+ // or the resource type is "external"
+ if (jpaFile != null) {
+ jpaFile.removeRootStructureNode(this.name, this);
+ }
+ }
+
+
+ // ********** 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;
+ }
+ Iterator<String> values = this.mapping.javaCompletionProposals(pos, filter, astRoot);
+ if (values != null) {
+ return values;
+ }
+ for (JavaPersistentAttribute attribute : this.getAttributes()) {
+ values = attribute.javaCompletionProposals(pos, filter, astRoot);
+ if (values != null) {
+ return values;
+ }
+ }
+ return EmptyIterator.instance();
+ }
+
+
+ // ********** validation **********
+
+ public void validate(List<IMessage> messages, IReporter reporter) {
+ if (reporter.isCancelled()) {
+ throw new ValidationCancelledException();
+ }
+ // TODO temporary hack since we don't know yet where to put
+ // any messages for types in another project (e.g. referenced by
+ // persistence.xml)
+ IFile file = this.resourcePersistentType.getFile();
+ // 'file' will be null if the type is "external" and binary;
+ // the file will be in a different project if the type is "external" and source;
+ // the type will be binary if it is in a JAR in the current project
+ if ((file != null) && file.getProject().equals(this.getJpaProject().getProject()) &&
+ (this.resourcePersistentType instanceof SourceNode)) {
+ // build the AST root here to pass down
+ this.validate(messages, reporter, this.buildASTRoot());
+ }
+ }
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.validateMapping(messages, reporter, astRoot);
+ this.validateAttributes(messages, reporter, astRoot);
+ }
+
+ protected void validateMapping(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ try {
+ this.mapping.validate(messages, reporter, astRoot);
+ } catch(Throwable t) {
+ JptJpaCorePlugin.log(t);
+ }
+ }
+
+ protected void validateAttributes(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ for (JavaPersistentAttribute attribute : this.getAttributes()) {
+ this.validateAttribute(attribute, reporter, messages, astRoot);
+ }
+ }
+
+ protected void validateAttribute(JavaPersistentAttribute attribute, IReporter reporter, List<IMessage> messages, CompilationUnit astRoot) {
+ try {
+ attribute.validate(messages, reporter, astRoot);
+ } catch(Throwable t) {
+ JptJpaCorePlugin.log(t);
+ }
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getSelectionTextRange(astRoot);
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public PersistentType.Owner getParent() {
+ return (PersistentType.Owner) super.getParent();
+ }
+
+ @Override
+ public IResource getResource() {
+ return this.resourcePersistentType.getFile();
+ }
+
+ public JavaResourcePersistentType getResourcePersistentType() {
+ return this.resourcePersistentType;
+ }
+
+ public AccessType getOwnerOverrideAccess() {
+ return this.getParent().getOverridePersistentTypeAccess();
+ }
+
+ public AccessType getOwnerDefaultAccess() {
+ return this.getParent().getDefaultPersistentTypeAccess();
+ }
+
+ protected CompilationUnit buildASTRoot() {
+ return this.resourcePersistentType.getJavaResourceCompilationUnit().buildASTRoot();
+ }
+
+ protected JpaFile getJpaFile() {
+ return this.getJpaFile(this.resourcePersistentType.getFile());
+ }
+
+ public boolean isFor(String typeName) {
+ return Tools.valuesAreEqual(typeName, this.getName());
+ }
+
+ public boolean isIn(IPackageFragment packageFragment) {
+ return Tools.valuesAreEqual(packageFragment.getElementName(), this.getPackageName());
+ }
+
+ protected String getPackageName() {
+ return this.getResourcePersistentType().getPackageName();
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.name);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaQuery.java
new file mode 100644
index 0000000000..9f92fa8592
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaQuery.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.Vector;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.jpa.core.context.Query;
+import org.eclipse.jpt.jpa.core.context.QueryHint;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaQuery;
+import org.eclipse.jpt.jpa.core.context.java.JavaQueryHint;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+import org.eclipse.jpt.jpa.core.resource.java.QueryAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.QueryHintAnnotation;
+
+/**
+ * Java query
+ */
+public abstract class AbstractJavaQuery<A extends QueryAnnotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaQuery
+{
+ protected final A queryAnnotation;
+
+ protected String name;
+
+ protected String query;
+
+ protected final Vector<JavaQueryHint> hints = new Vector<JavaQueryHint>();
+ protected final HintContainerAdapter hintContainerAdapter = new HintContainerAdapter();
+
+
+ protected AbstractJavaQuery(JavaJpaContextNode parent, A queryAnnotation) {
+ super(parent);
+ this.queryAnnotation = queryAnnotation;
+ this.name = queryAnnotation.getName();
+ this.query = queryAnnotation.getQuery();
+ this.initializeHints();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setName_(this.queryAnnotation.getName());
+ this.setQuery_(this.queryAnnotation.getQuery());
+ this.syncHints();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateNodes(this.getHints());
+ this.getPersistenceUnit().addQuery(this);
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.queryAnnotation.setName(name);
+ this.setName_(name);
+ }
+
+ protected void setName_(String name) {
+ String old = this.name;
+ this.name = name;
+ this.firePropertyChanged(NAME_PROPERTY, old, name);
+ }
+
+
+ // ********** query **********
+
+ public String getQuery() {
+ return this.query;
+ }
+
+ public void setQuery(String query) {
+ this.queryAnnotation.setQuery(query);
+ this.setQuery_(query);
+ }
+
+ protected void setQuery_(String query) {
+ String old = this.query;
+ this.query = query;
+ this.firePropertyChanged(QUERY_PROPERTY, old, query);
+ }
+
+
+ // ********** hints **********
+
+ public ListIterable<JavaQueryHint> getHints() {
+ return new LiveCloneListIterable<JavaQueryHint>(this.hints);
+ }
+
+ public int getHintsSize() {
+ return this.hints.size();
+ }
+
+ public JavaQueryHint addHint() {
+ return this.addHint(this.hints.size());
+ }
+
+ public JavaQueryHint addHint(int index) {
+ QueryHintAnnotation annotation = this.queryAnnotation.addHint(index);
+ return this.addHint_(index, annotation);
+ }
+
+ public void removeHint(QueryHint hint) {
+ this.removeHint(this.hints.indexOf(hint));
+ }
+
+ public void removeHint(int index) {
+ this.queryAnnotation.removeHint(index);
+ this.removeHint_(index);
+ }
+
+ protected void removeHint_(int index) {
+ this.removeItemFromList(index, this.hints, HINTS_LIST);
+ }
+
+ public void moveHint(int targetIndex, int sourceIndex) {
+ this.queryAnnotation.moveHint(targetIndex, sourceIndex);
+ this.moveItemInList(targetIndex, sourceIndex, this.hints, HINTS_LIST);
+ }
+
+ protected void initializeHints() {
+ for (Iterator<QueryHintAnnotation> stream = this.queryAnnotation.hints(); stream.hasNext(); ) {
+ this.hints.add(this.buildHint(stream.next()));
+ }
+ }
+
+ protected JavaQueryHint buildHint(QueryHintAnnotation hintAnnotation) {
+ return this.getJpaFactory().buildJavaQueryHint(this, hintAnnotation);
+ }
+
+ protected void syncHints() {
+ ContextContainerTools.synchronizeWithResourceModel(this.hintContainerAdapter);
+ }
+
+ protected Iterable<QueryHintAnnotation> getHintAnnotations() {
+ return CollectionTools.iterable(this.queryAnnotation.hints());
+ }
+
+ protected void moveHint_(int index, JavaQueryHint hint) {
+ this.moveItemInList(index, hint, this.hints, HINTS_LIST);
+ }
+
+ protected JavaQueryHint addHint_(int index, QueryHintAnnotation hintAnnotation) {
+ JavaQueryHint hint = this.buildHint(hintAnnotation);
+ this.addItemToList(index, hint, this.hints, HINTS_LIST);
+ return hint;
+ }
+
+ protected void removeHint_(JavaQueryHint hint) {
+ this.removeHint_(this.hints.indexOf(hint));
+ }
+
+ /**
+ * hint container adapter
+ */
+ protected class HintContainerAdapter
+ implements ContextContainerTools.Adapter<JavaQueryHint, QueryHintAnnotation>
+ {
+ public Iterable<JavaQueryHint> getContextElements() {
+ return AbstractJavaQuery.this.getHints();
+ }
+ public Iterable<QueryHintAnnotation> getResourceElements() {
+ return AbstractJavaQuery.this.getHintAnnotations();
+ }
+ public QueryHintAnnotation getResourceElement(JavaQueryHint contextElement) {
+ return contextElement.getQueryHintAnnotation();
+ }
+ public void moveContextElement(int index, JavaQueryHint element) {
+ AbstractJavaQuery.this.moveHint_(index, element);
+ }
+ public void addContextElement(int index, QueryHintAnnotation resourceElement) {
+ AbstractJavaQuery.this.addHint_(index, resourceElement);
+ }
+ public void removeContextElement(JavaQueryHint element) {
+ AbstractJavaQuery.this.removeHint_(element);
+ }
+ }
+
+
+ // ********** misc **********
+
+ public A getQueryAnnotation() {
+ return this.queryAnnotation;
+ }
+
+ public boolean overrides(Query other) {
+ return MappingTools.nodeOverrides(this, other, PRECEDENCE_TYPE_LIST);
+ }
+
+ public boolean duplicates(Query other) {
+ return MappingTools.nodesAreDuplicates(this, other);
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.queryAnnotation.getTextRange(astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return this.queryAnnotation.getNameTextRange(astRoot);
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.name);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaReadOnlyUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaReadOnlyUniqueConstraint.java
new file mode 100644
index 0000000000..053fe6fb83
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaReadOnlyUniqueConstraint.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Vector;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaReadOnlyUniqueConstraint;
+
+public abstract class AbstractJavaReadOnlyUniqueConstraint
+ extends AbstractJavaJpaContextNode
+ implements JavaReadOnlyUniqueConstraint
+{
+ protected final Vector<String> columnNames = new Vector<String>();
+
+
+ public AbstractJavaReadOnlyUniqueConstraint(JavaJpaContextNode parent) {
+ super(parent);
+ }
+
+
+ // ********** column names **********
+
+ public Iterable<String> getColumnNames() {
+ return new LiveCloneIterable<String>(this.columnNames);
+ }
+
+ public int getColumnNamesSize() {
+ return this.columnNames.size();
+ }
+
+ public String getColumnName(int index) {
+ return this.columnNames.get(index);
+ }
+
+ protected void syncColumnNames() {
+ this.synchronizeList(this.getResourceColumnNames(), this.columnNames, COLUMN_NAMES_LIST);
+ }
+
+ protected abstract Iterable<String> getResourceColumnNames();
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.columnNames);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaRelationshipMapping.java
new file mode 100644
index 0000000000..95788f0127
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaRelationshipMapping.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.FetchType;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaCascade;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappingRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipMapping;
+import org.eclipse.jpt.jpa.core.internal.context.AttributeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaCascade;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField;
+import org.eclipse.jpt.jpa.core.resource.java.RelationshipMappingAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java relationship mapping (1:1, 1:m, m:1, m:m)
+ */
+public abstract class AbstractJavaRelationshipMapping<A extends RelationshipMappingAnnotation>
+ extends AbstractJavaAttributeMapping<A>
+ implements JavaRelationshipMapping
+{
+ protected String specifiedTargetEntity;
+ protected String defaultTargetEntity;
+ protected String fullyQualifiedTargetEntity;
+
+ protected final JavaMappingRelationship relationship;
+
+ protected final JavaCascade cascade;
+
+ protected FetchType specifiedFetch;
+ protected FetchType defaultFetch;
+
+
+ protected AbstractJavaRelationshipMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.specifiedTargetEntity = this.buildSpecifiedTargetEntity();
+ this.relationship = this.buildRelationship();
+ this.cascade = this.buildCascade();
+ this.specifiedFetch = this.buildSpecifiedFetch();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedTargetEntity_(this.buildSpecifiedTargetEntity());
+ this.relationship.synchronizeWithResourceModel();
+ this.cascade.synchronizeWithResourceModel();
+ this.setSpecifiedFetch_(this.buildSpecifiedFetch());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultTargetEntity(this.buildDefaultTargetEntity());
+ this.setFullyQualifiedTargetEntity(this.buildFullyQualifiedTargetEntity());
+ this.relationship.update();
+ this.cascade.update();
+ this.setDefaultFetch(this.buildDefaultFetch());
+ }
+
+
+ // ********** target entity **********
+
+ public String getTargetEntity() {
+ return (this.specifiedTargetEntity != null) ? this.specifiedTargetEntity : this.defaultTargetEntity;
+ }
+
+ public String getSpecifiedTargetEntity() {
+ return this.specifiedTargetEntity;
+ }
+
+ public void setSpecifiedTargetEntity(String entity) {
+ if (this.valuesAreDifferent(entity, this.specifiedTargetEntity)) {
+ this.getAnnotationForUpdate().setTargetEntity(entity);
+ this.setSpecifiedTargetEntity_(entity);
+ }
+ }
+
+ protected void setSpecifiedTargetEntity_(String entity) {
+ String old = this.specifiedTargetEntity;
+ this.specifiedTargetEntity = entity;
+ this.firePropertyChanged(SPECIFIED_TARGET_ENTITY_PROPERTY, old, entity);
+ }
+
+ protected String buildSpecifiedTargetEntity() {
+ A annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getTargetEntity();
+ }
+
+ public String getDefaultTargetEntity() {
+ return this.defaultTargetEntity;
+ }
+
+ protected void setDefaultTargetEntity(String entity) {
+ String old = this.defaultTargetEntity;
+ this.defaultTargetEntity = entity;
+ this.firePropertyChanged(DEFAULT_TARGET_ENTITY_PROPERTY, old, entity);
+ }
+
+ protected abstract String buildDefaultTargetEntity();
+
+ public String getFullyQualifiedTargetEntity() {
+ return this.fullyQualifiedTargetEntity;
+ }
+
+ protected void setFullyQualifiedTargetEntity(String entity) {
+ String old = this.fullyQualifiedTargetEntity;
+ this.fullyQualifiedTargetEntity = entity;
+ this.firePropertyChanged(FULLY_QUALIFIED_TARGET_ENTITY_PROPERTY, old, entity);
+ }
+
+ protected String buildFullyQualifiedTargetEntity() {
+ return (this.specifiedTargetEntity == null) ?
+ this.defaultTargetEntity :
+ this.getMappingAnnotation().getFullyQualifiedTargetEntityClassName();
+ }
+
+ public Entity getResolvedTargetEntity() {
+ return (this.fullyQualifiedTargetEntity == null) ? null : this.getPersistenceUnit().getEntity(this.fullyQualifiedTargetEntity);
+ }
+
+ // sub-classes like this to be public
+ public PersistentType getResolvedTargetType() {
+ return (this.fullyQualifiedTargetEntity == null) ? null : this.getPersistenceUnit().getPersistentType(this.fullyQualifiedTargetEntity);
+ }
+
+ public char getTargetEntityEnclosingTypeSeparator() {
+ return '.';
+ }
+
+
+ // ********** relationship reference **********
+
+ public JavaMappingRelationship getRelationship() {
+ return this.relationship;
+ }
+
+ protected abstract JavaMappingRelationship buildRelationship();
+
+
+ // ********** cascade **********
+
+ public JavaCascade getCascade() {
+ return this.cascade;
+ }
+
+ protected JavaCascade buildCascade() {
+ // NB: we don't use the platform
+ return new GenericJavaCascade(this);
+ }
+
+
+ // ********** fetch **********
+
+ public FetchType getFetch() {
+ return (this.specifiedFetch != null) ? this.specifiedFetch : this.defaultFetch;
+ }
+
+ public FetchType getSpecifiedFetch() {
+ return this.specifiedFetch;
+ }
+
+ public void setSpecifiedFetch(FetchType fetch) {
+ if (this.valuesAreDifferent(fetch, this.specifiedFetch)) {
+ this.getAnnotationForUpdate().setFetch(FetchType.toJavaResourceModel(fetch));
+ this.setSpecifiedFetch_(fetch);
+ }
+ }
+
+ protected void setSpecifiedFetch_(FetchType fetch) {
+ FetchType old = this.specifiedFetch;
+ this.specifiedFetch = fetch;
+ this.firePropertyChanged(SPECIFIED_FETCH_PROPERTY, old, fetch);
+ }
+
+ protected FetchType buildSpecifiedFetch() {
+ A annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : FetchType.fromJavaResourceModel(annotation.getFetch());
+ }
+
+ public FetchType getDefaultFetch() {
+ return this.defaultFetch;
+ }
+
+ protected void setDefaultFetch(FetchType fetch) {
+ FetchType old = this.defaultFetch;
+ this.defaultFetch = fetch;
+ this.firePropertyChanged(DEFAULT_FETCH_PROPERTY, old, fetch);
+ }
+
+ protected abstract FetchType buildDefaultFetch();
+
+
+ // ********** misc **********
+
+ @Override
+ public boolean isRelationshipOwner() {
+ return this.relationship.isOwner();
+ }
+
+ @Override
+ public boolean isOwnedBy(AttributeMapping mapping) {
+ return mapping.isRelationshipOwner() &&
+ this.relationship.isOwnedBy((RelationshipMapping) mapping);
+ }
+
+ public RelationshipMapping getRelationshipOwner() {
+ Entity entity = this.getResolvedTargetEntity();
+ if (entity == null) {
+ return null;
+ }
+ for (ReadOnlyPersistentAttribute attribute : CollectionTools.iterable(entity.getPersistentType().allAttributes())) {
+ AttributeMapping mapping = attribute.getMapping();
+ if (this.isOwnedBy(mapping)) {
+ return (RelationshipMapping) mapping;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isOverridableAssociationMapping() {
+ return this.relationship.isOverridable();
+ }
+
+ public Iterator<String> allTargetEntityAttributeNames() {
+ return new CompositeIterator<String>(this.allTargetEntityAttributeNamesLists());
+ }
+
+ protected Iterator<Iterator<String>> allTargetEntityAttributeNamesLists() {
+ return new TransformationIterator<AttributeMapping, Iterator<String>>(this.allTargetEntityAttributeMappings(), AttributeMappingTools.ALL_MAPPING_NAMES_TRANSFORMER);
+ }
+
+ protected Iterator<AttributeMapping> allTargetEntityAttributeMappings() {
+ Entity entity = this.getResolvedTargetEntity();
+ return (entity != null) ? entity.allAttributeMappings() : EmptyIterator.<AttributeMapping> instance();
+ }
+
+ protected String getTargetEntityIdAttributeName() {
+ PersistentAttribute attribute = this.getTargetEntityIdAttribute();
+ return (attribute == null) ? null : attribute.getName();
+ }
+
+ protected PersistentAttribute getTargetEntityIdAttribute() {
+ Entity entity = this.getResolvedTargetEntity();
+ return (entity == null) ? null : entity.getIdAttribute();
+ }
+
+
+ // ********** 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.relationship.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return null;
+ }
+
+
+ // ********** metamodel **********
+
+ @Override
+ public String getMetamodelTypeName() {
+ return (this.fullyQualifiedTargetEntity != null) ? this.fullyQualifiedTargetEntity : MetamodelField.DEFAULT_TYPE_NAME;
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.validateTargetEntity(messages, astRoot);
+ this.relationship.validate(messages, reporter, astRoot);
+ }
+
+ protected void validateTargetEntity(List<IMessage> messages, CompilationUnit astRoot) {
+ if (this.getTargetEntity() == null) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.TARGET_ENTITY_NOT_DEFINED,
+ new String[] {this.getName()},
+ this,
+ this.getValidationTextRange(astRoot)
+ )
+ );
+ }
+ else if (this.getResolvedTargetEntity() == null) {
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.TARGET_ENTITY_IS_NOT_AN_ENTITY,
+ new String[] {this.getTargetEntity(), this.getName()},
+ this,
+ this.getTargetEntityTextRange(astRoot)
+ )
+ );
+ }
+ }
+
+ protected TextRange getTargetEntityTextRange(CompilationUnit astRoot) {
+ A annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : this.getTextRange(annotation.getTargetEntityTextRange(astRoot), astRoot);
+ }
+
+ protected TextRange getTextRange(TextRange textRange, CompilationUnit astRoot) {
+ return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSequenceGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSequenceGenerator.java
new file mode 100644
index 0000000000..c81dbb41b1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSequenceGenerator.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaSequenceGenerator;
+import org.eclipse.jpt.jpa.core.resource.java.SequenceGeneratorAnnotation;
+import org.eclipse.jpt.jpa.db.Schema;
+
+/**
+ * Java sequence generator
+ */
+public abstract class AbstractJavaSequenceGenerator<A extends SequenceGeneratorAnnotation>
+ extends AbstractJavaGenerator<A>
+ implements JavaSequenceGenerator
+{
+ protected String specifiedSequenceName;
+ protected String defaultSequenceName;
+
+
+ protected AbstractJavaSequenceGenerator(JavaJpaContextNode parent, A generatorAnnotation) {
+ super(parent, generatorAnnotation);
+ this.specifiedSequenceName = generatorAnnotation.getSequenceName();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedSequenceName_(this.generatorAnnotation.getSequenceName());
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultSequenceName(this.buildDefaultSequenceName());
+ }
+
+
+ // ********** initial value **********
+
+ @Override
+ protected int buildDefaultInitialValue() {
+ return DEFAULT_INITIAL_VALUE;
+ }
+
+
+ // ********** sequence name **********
+
+ public String getSequenceName() {
+ return (this.specifiedSequenceName != null) ? this.specifiedSequenceName : this.defaultSequenceName;
+ }
+
+ public String getSpecifiedSequenceName() {
+ return this.specifiedSequenceName;
+ }
+
+ public void setSpecifiedSequenceName(String name) {
+ this.generatorAnnotation.setSequenceName(name);
+ this.setSpecifiedSequenceName_(name);
+ }
+
+ protected void setSpecifiedSequenceName_(String name) {
+ String old = this.specifiedSequenceName;
+ this.specifiedSequenceName = name;
+ this.firePropertyChanged(SPECIFIED_SEQUENCE_NAME_PROPERTY, old, name);
+ }
+
+ public String getDefaultSequenceName() {
+ return this.defaultSequenceName;
+ }
+
+ protected void setDefaultSequenceName(String name) {
+ String old = this.defaultSequenceName;
+ this.defaultSequenceName = name;
+ this.firePropertyChanged(DEFAULT_SEQUENCE_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildDefaultSequenceName() {
+ return null; // TODO the default sequence name is determined by the runtime provider...
+ }
+
+
+ // ********** Java completion proposals **********
+
+ /**
+ * called if the database is connected:
+ * sequenceName
+ */
+ @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.sequenceNameTouches(pos, astRoot)) {
+ return this.getJavaCandidateSequences(filter).iterator();
+ }
+ return null;
+ }
+
+ protected boolean sequenceNameTouches(int pos, CompilationUnit astRoot) {
+ return this.generatorAnnotation.sequenceNameTouches(pos, astRoot);
+ }
+
+ protected Iterable<String> getJavaCandidateSequences(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.getCandidateSequences(filter));
+ }
+
+ protected Iterable<String> getCandidateSequences(Filter<String> filter) {
+ return new FilteringIterable<String>(this.getCandidateSequences(), filter);
+ }
+
+ protected Iterable<String> getCandidateSequences() {
+ Schema dbSchema = this.getDbSchema();
+ return (dbSchema != null) ? dbSchema.getSortedSequenceIdentifiers() : EmptyIterable.<String> instance();
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSingleRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSingleRelationshipMapping.java
new file mode 100644
index 0000000000..38ee6dc2c2
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaSingleRelationshipMapping.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.context.FetchType;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.NullJavaDerivedIdentity2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaDerivedIdentity2_0;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaSingleRelationshipMapping2_0;
+import org.eclipse.jpt.jpa.core.resource.java.SingleRelationshipMappingAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java single relationship mapping (1:1, m:1)
+ */
+public abstract class AbstractJavaSingleRelationshipMapping<A extends SingleRelationshipMappingAnnotation>
+ extends AbstractJavaRelationshipMapping<A>
+ implements JavaSingleRelationshipMapping2_0
+{
+ protected Boolean specifiedOptional;
+ protected boolean defaultOptional;
+
+ protected final JavaDerivedIdentity2_0 derivedIdentity;
+
+
+ protected AbstractJavaSingleRelationshipMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.specifiedOptional = this.buildSpecifiedOptional();
+ this.derivedIdentity = this.buildDerivedIdentity();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedOptional_(this.buildSpecifiedOptional());
+ this.derivedIdentity.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultOptional(this.buildDefaultOptional());
+ this.derivedIdentity.update();
+ }
+
+
+ // ********** optional **********
+
+ public boolean isOptional() {
+ return (this.specifiedOptional != null) ? this.specifiedOptional.booleanValue() : this.defaultOptional;
+ }
+
+ public Boolean getSpecifiedOptional() {
+ return this.specifiedOptional;
+ }
+
+ public void setSpecifiedOptional(Boolean optional) {
+ if (this.valuesAreDifferent(optional, this.specifiedOptional)) {
+ this.getAnnotationForUpdate().setOptional(optional);
+ this.setSpecifiedOptional_(optional);
+ }
+ }
+
+ protected void setSpecifiedOptional_(Boolean optional) {
+ Boolean old = this.specifiedOptional;
+ this.specifiedOptional = optional;
+ this.firePropertyChanged(SPECIFIED_OPTIONAL_PROPERTY, old, optional);
+ }
+
+ protected Boolean buildSpecifiedOptional() {
+ A annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getOptional();
+ }
+
+ public boolean isDefaultOptional() {
+ return this.defaultOptional;
+ }
+
+ protected void setDefaultOptional(boolean optional) {
+ boolean old = this.defaultOptional;
+ this.defaultOptional = optional;
+ this.firePropertyChanged(DEFAULT_OPTIONAL_PROPERTY, old, optional);
+ }
+
+ protected boolean buildDefaultOptional() {
+ return DEFAULT_OPTIONAL;
+ }
+
+
+ // ********** derived identity **********
+
+ public JavaDerivedIdentity2_0 getDerivedIdentity() {
+ return this.derivedIdentity;
+ }
+
+ protected JavaDerivedIdentity2_0 buildDerivedIdentity() {
+ return this.isJpa2_0Compatible() ?
+ this.getJpaFactory2_0().buildJavaDerivedIdentity(this) :
+ new NullJavaDerivedIdentity2_0(this);
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ protected FetchType buildDefaultFetch() {
+ return DEFAULT_FETCH_TYPE;
+ }
+
+ @Override
+ protected String buildDefaultTargetEntity() {
+ return this.getPersistentAttribute().getSingleReferenceTargetTypeName();
+ }
+
+
+ // ********** 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.derivedIdentity.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.derivedIdentity.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTable.java
new file mode 100644
index 0000000000..302f4af238
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTable.java
@@ -0,0 +1,584 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.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.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.NameTools;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyTable;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyUniqueConstraint;
+import org.eclipse.jpt.jpa.core.context.UniqueConstraint;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaUniqueConstraint;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver;
+import org.eclipse.jpt.jpa.core.resource.java.BaseTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.UniqueConstraintAnnotation;
+import org.eclipse.jpt.jpa.db.Catalog;
+import org.eclipse.jpt.jpa.db.Database;
+import org.eclipse.jpt.jpa.db.Schema;
+import org.eclipse.jpt.jpa.db.SchemaContainer;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java table, secondary table, join table, or collection table
+ * <p>
+ * <strong>NB:</strong> any subclass that directly holds its table
+ * annotation must:<ul>
+ * <li>call the "super" constructor that takes a table annotation
+ * {@link #AbstractJavaTable(JavaJpaContextNode, org.eclipse.jpt.jpa.core.context.Table.Owner, BaseTableAnnotation)}
+ * <li>override {@link #setTableAnnotation(BaseTableAnnotation)} to set the table
+ * annotation so it is in place before the table's state
+ * (e.g. {@link #specifiedName}) is initialized
+ * </ul>
+ */
+public abstract class AbstractJavaTable<A extends BaseTableAnnotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaTable, UniqueConstraint.Owner
+{
+ protected final Owner owner;
+
+ protected String specifiedName;
+ protected String defaultName;
+
+ protected String specifiedSchema;
+ protected String defaultSchema;
+
+ protected String specifiedCatalog;
+ protected String defaultCatalog;
+
+ protected final Vector<JavaUniqueConstraint> uniqueConstraints = new Vector<JavaUniqueConstraint>();
+ protected final UniqueConstraintContainerAdapter uniqueConstraintContainerAdapter = new UniqueConstraintContainerAdapter();
+
+
+ protected AbstractJavaTable(JavaJpaContextNode parent, Owner owner) {
+ this(parent, owner, null);
+ }
+
+ protected AbstractJavaTable(JavaJpaContextNode parent, Owner owner, A tableAnnotation) {
+ super(parent);
+ this.owner = owner;
+ this.setTableAnnotation(tableAnnotation);
+ this.specifiedName = this.buildSpecifiedName();
+ this.specifiedSchema = this.buildSpecifiedSchema();
+ this.specifiedCatalog = this.buildSpecifiedCatalog();
+ this.initializeUniqueConstraints();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setSpecifiedName_(this.buildSpecifiedName());
+ this.setSpecifiedSchema_(this.buildSpecifiedSchema());
+ this.setSpecifiedCatalog_(this.buildSpecifiedCatalog());
+ this.syncUniqueConstraints();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setDefaultName(this.buildDefaultName());
+ this.setDefaultSchema(this.buildDefaultSchema());
+ this.setDefaultCatalog(this.buildDefaultCatalog());
+ this.updateNodes(this.getUniqueConstraints());
+ }
+
+
+ // ********** table annotation **********
+
+ /**
+ * Return the Java table annotation. Do not return <code>null</code> if the
+ * Java annotation does not exist; return a <em>null</em> table annotation
+ * instead.
+ */
+ public abstract A getTableAnnotation();
+
+ /**
+ * see class comment... ({@link AbstractJavaTable})
+ */
+ protected void setTableAnnotation(A tableAnnotation) {
+ if (tableAnnotation != null) {
+ throw new IllegalArgumentException("this method must be overridden if the table annotation is not null: " + tableAnnotation); //$NON-NLS-1$
+ }
+ }
+
+ protected void removeTableAnnotationIfUnset() {
+ if (this.getTableAnnotation().isUnset()) {
+ this.removeTableAnnotation();
+ }
+ }
+
+ protected abstract void removeTableAnnotation();
+
+ public boolean isSpecifiedInResource() {
+ return this.getTableAnnotation().isSpecified();
+ }
+
+
+ // ********** name **********
+
+ public String getName() {
+ return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
+ }
+
+ public String getSpecifiedName() {
+ return this.specifiedName;
+ }
+
+ public void setSpecifiedName(String name) {
+ if (this.valuesAreDifferent(this.specifiedName, name)) {
+ this.getTableAnnotation().setName(name);
+ this.removeTableAnnotationIfUnset();
+ this.setSpecifiedName_(name);
+ }
+ }
+
+ protected void setSpecifiedName_(String name) {
+ String old = this.specifiedName;
+ this.specifiedName = name;
+ this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildSpecifiedName() {
+ return this.getTableAnnotation().getName();
+ }
+
+ public String getDefaultName() {
+ return this.defaultName;
+ }
+
+ protected void setDefaultName(String name) {
+ String old = this.defaultName;
+ this.defaultName = name;
+ this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
+ }
+
+ protected abstract String buildDefaultName();
+
+
+ // ********** schema **********
+
+ public String getSchema() {
+ return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema;
+ }
+
+ public String getSpecifiedSchema() {
+ return this.specifiedSchema;
+ }
+
+ public void setSpecifiedSchema(String schema) {
+ if (this.valuesAreDifferent(this.specifiedSchema, schema)) {
+ this.getTableAnnotation().setSchema(schema);
+ this.removeTableAnnotationIfUnset();
+ this.setSpecifiedSchema_(schema);
+ }
+ }
+
+ protected void setSpecifiedSchema_(String schema) {
+ String old = this.specifiedSchema;
+ this.specifiedSchema = schema;
+ this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema);
+ }
+
+ protected String buildSpecifiedSchema() {
+ return this.getTableAnnotation().getSchema();
+ }
+
+ 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);
+ }
+
+ protected abstract String buildDefaultSchema();
+
+
+ // ********** catalog **********
+
+ public String getCatalog() {
+ return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog;
+ }
+
+ public String getSpecifiedCatalog() {
+ return this.specifiedCatalog;
+ }
+
+ public void setSpecifiedCatalog(String catalog) {
+ if (this.valuesAreDifferent(this.specifiedCatalog, catalog)) {
+ this.getTableAnnotation().setCatalog(catalog);
+ this.removeTableAnnotationIfUnset();
+ this.setSpecifiedCatalog_(catalog);
+ }
+ }
+
+ protected void setSpecifiedCatalog_(String catalog) {
+ String old = this.specifiedCatalog;
+ this.specifiedCatalog = catalog;
+ this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog);
+ }
+
+ protected String buildSpecifiedCatalog() {
+ return this.getTableAnnotation().getCatalog();
+ }
+
+ 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);
+ }
+
+ protected abstract String buildDefaultCatalog();
+
+
+ // ********** unique constraints **********
+
+ public ListIterator<JavaUniqueConstraint> uniqueConstraints() {
+ return this.getUniqueConstraints().iterator();
+ }
+
+ protected ListIterable<JavaUniqueConstraint> getUniqueConstraints() {
+ return new LiveCloneListIterable<JavaUniqueConstraint>(this.uniqueConstraints);
+ }
+
+ public int uniqueConstraintsSize() {
+ return this.uniqueConstraints.size();
+ }
+
+ public JavaUniqueConstraint getUniqueConstraint(int index) {
+ return this.uniqueConstraints.get(index);
+ }
+
+ public JavaUniqueConstraint addUniqueConstraint() {
+ return this.addUniqueConstraint(this.uniqueConstraints.size());
+ }
+
+ public JavaUniqueConstraint addUniqueConstraint(int index) {
+ UniqueConstraintAnnotation annotation = this.getTableAnnotation().addUniqueConstraint(index);
+ return this.addUniqueConstraint_(index, annotation);
+ }
+
+ public void removeUniqueConstraint(UniqueConstraint constraint) {
+ this.removeUniqueConstraint(this.uniqueConstraints.indexOf(constraint));
+ }
+
+ public void removeUniqueConstraint(int index) {
+ this.getTableAnnotation().removeUniqueConstraint(index);
+ this.removeTableAnnotationIfUnset();
+ this.removeUniqueConstraint_(index);
+ }
+
+ protected void removeUniqueConstraint_(int index) {
+ this.removeItemFromList(index, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ }
+
+ public void moveUniqueConstraint(int targetIndex, int sourceIndex) {
+ this.getTableAnnotation().moveUniqueConstraint(targetIndex, sourceIndex);
+ this.moveItemInList(targetIndex, sourceIndex, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ }
+
+ protected void initializeUniqueConstraints() {
+ for (Iterator<UniqueConstraintAnnotation> stream = this.getTableAnnotation().uniqueConstraints(); stream.hasNext(); ) {
+ this.uniqueConstraints.add(this.buildUniqueConstraint(stream.next()));
+ }
+ }
+
+ protected JavaUniqueConstraint buildUniqueConstraint(UniqueConstraintAnnotation constraintAnnotation) {
+ return this.getJpaFactory().buildJavaUniqueConstraint(this, this, constraintAnnotation);
+ }
+
+ protected void syncUniqueConstraints() {
+ ContextContainerTools.synchronizeWithResourceModel(this.uniqueConstraintContainerAdapter);
+ }
+
+ protected Iterable<UniqueConstraintAnnotation> getUniqueConstraintAnnotations() {
+ return CollectionTools.iterable(this.getTableAnnotation().uniqueConstraints());
+ }
+
+ protected void moveUniqueConstraint_(int index, JavaUniqueConstraint constraint) {
+ this.moveItemInList(index, constraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ }
+
+ protected JavaUniqueConstraint addUniqueConstraint_(int index, UniqueConstraintAnnotation constraintAnnotation) {
+ JavaUniqueConstraint constraint = this.buildUniqueConstraint(constraintAnnotation);
+ this.addItemToList(index, constraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ return constraint;
+ }
+
+ protected void removeUniqueConstraint_(JavaUniqueConstraint constraint) {
+ this.removeUniqueConstraint_(this.uniqueConstraints.indexOf(constraint));
+ }
+
+ /**
+ * unique constraint container adapter
+ */
+ protected class UniqueConstraintContainerAdapter
+ implements ContextContainerTools.Adapter<JavaUniqueConstraint, UniqueConstraintAnnotation>
+ {
+ public Iterable<JavaUniqueConstraint> getContextElements() {
+ return AbstractJavaTable.this.getUniqueConstraints();
+ }
+ public Iterable<UniqueConstraintAnnotation> getResourceElements() {
+ return AbstractJavaTable.this.getUniqueConstraintAnnotations();
+ }
+ public UniqueConstraintAnnotation getResourceElement(JavaUniqueConstraint contextElement) {
+ return contextElement.getUniqueConstraintAnnotation();
+ }
+ public void moveContextElement(int index, JavaUniqueConstraint element) {
+ AbstractJavaTable.this.moveUniqueConstraint_(index, element);
+ }
+ public void addContextElement(int index, UniqueConstraintAnnotation resourceElement) {
+ AbstractJavaTable.this.addUniqueConstraint_(index, resourceElement);
+ }
+ public void removeContextElement(JavaUniqueConstraint element) {
+ AbstractJavaTable.this.removeUniqueConstraint_(element);
+ }
+ }
+
+
+ // ********** database stuff **********
+
+ public org.eclipse.jpt.jpa.db.Table getDbTable() {
+ Schema dbSchema = this.getDbSchema();
+ return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getName());
+ }
+
+ public Schema getDbSchema() {
+ SchemaContainer dbSchemaContainer = this.getDbSchemaContainer();
+ return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema());
+ }
+
+ /**
+ * 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.resolveDbCatalog(catalog) : this.getDatabase();
+ }
+
+ /**
+ * 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.resolveDbCatalog(catalog);
+ }
+
+ public boolean isResolved() {
+ return this.getDbTable() != null;
+ }
+
+ public boolean schemaIsResolved() {
+ return this.getDbSchema() != null;
+ }
+
+ /**
+ * 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 boolean catalogIsResolved() {
+ String catalog = this.getCatalog();
+ return (catalog == null) || (this.resolveDbCatalog(catalog) != null);
+ }
+
+
+ // ********** UniqueConstraint.Owner implementation **********
+
+ public Iterator<String> candidateUniqueConstraintColumnNames() {
+ org.eclipse.jpt.jpa.db.Table dbTable = this.getDbTable();
+ return (dbTable != null) ? dbTable.getSortedColumnIdentifiers().iterator() : EmptyIterator.<String>instance();
+ }
+
+
+ // ********** 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:
+ * name, schema, catalog
+ */
+ @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.nameTouches(pos, astRoot)) {
+ return this.getJavaCandidateNames(filter).iterator();
+ }
+ if (this.schemaTouches(pos, astRoot)) {
+ return this.getJavaCandidateSchemata(filter).iterator();
+ }
+ if (this.catalogTouches(pos, astRoot)) {
+ return this.getJavaCandidateCatalogs(filter).iterator();
+ }
+ return null;
+ }
+
+ protected boolean nameTouches(int pos, CompilationUnit astRoot) {
+ return this.getTableAnnotation().nameTouches(pos, astRoot);
+ }
+
+ protected Iterable<String> getJavaCandidateNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.getCandidateNames(filter));
+ }
+
+ protected Iterable<String> getCandidateNames(Filter<String> filter) {
+ return new FilteringIterable<String>(this.getCandidateNames(), filter);
+ }
+
+ protected Iterable<String> getCandidateNames() {
+ Schema dbSchema = this.getDbSchema();
+ return (dbSchema != null) ? dbSchema.getSortedTableIdentifiers() : EmptyIterable.<String> instance();
+ }
+
+ protected boolean schemaTouches(int pos, CompilationUnit astRoot) {
+ return this.getTableAnnotation().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() {
+ return this.getDbSchemaContainer().getSortedSchemaIdentifiers();
+ }
+
+ protected boolean catalogTouches(int pos, CompilationUnit astRoot) {
+ return this.getTableAnnotation().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();
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.buildTableValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildTableValidator(CompilationUnit astRoot) {
+ return this.owner.buildTableValidator(this, buildTextRangeResolver(astRoot));
+ }
+
+ protected TableTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaTableTextRangeResolver(this, astRoot);
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getTextRange(this.getTableAnnotation().getTextRange(astRoot), astRoot);
+ }
+
+ public TextRange getNameTextRange(CompilationUnit astRoot) {
+ return this.getTextRange(this.getTableAnnotation().getNameTextRange(astRoot), astRoot);
+ }
+
+ public TextRange getSchemaTextRange(CompilationUnit astRoot) {
+ return this.getTextRange(this.getTableAnnotation().getSchemaTextRange(astRoot), astRoot);
+ }
+
+ public TextRange getCatalogTextRange(CompilationUnit astRoot) {
+ return this.getTextRange(this.getTableAnnotation().getCatalogTextRange(astRoot), astRoot);
+ }
+
+ protected TextRange getTextRange(TextRange textRange, CompilationUnit astRoot) {
+ return (textRange != null) ? textRange : this.getParent().getValidationTextRange(astRoot);
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaJpaContextNode getParent() {
+ return (JavaJpaContextNode) super.getParent();
+ }
+
+ protected void initializeFrom(ReadOnlyTable oldTable) {
+ this.setSpecifiedName(oldTable.getSpecifiedName());
+ this.setSpecifiedCatalog(oldTable.getSpecifiedCatalog());
+ this.setSpecifiedSchema(oldTable.getSpecifiedSchema());
+ for (ReadOnlyUniqueConstraint constraint : CollectionTools.iterable(oldTable.uniqueConstraints())) {
+ this.addUniqueConstraint().initializeFrom(constraint);
+ }
+ }
+
+ protected void initializeFromVirtual(ReadOnlyTable virtualTable) {
+ this.setSpecifiedName(virtualTable.getName());
+ // ignore other settings?
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.buildQualifiedName());
+ }
+
+ protected String buildQualifiedName() {
+ return NameTools.buildQualifiedDatabaseObjectName(this.getCatalog(), this.getSchema(), this.getName());
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTypeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTypeMapping.java
new file mode 100644
index 0000000000..7aeada737c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaTypeMapping.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.NotNullFilter;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.Column;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyTable;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.internal.context.AttributeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTools;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericTypeMappingValidator;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
+import org.eclipse.jpt.jpa.db.Schema;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java type mapping
+ */
+public abstract class AbstractJavaTypeMapping<A extends Annotation>
+ extends AbstractJavaJpaContextNode
+ implements JavaTypeMapping
+{
+ // this can be null for a "null" type mapping
+ protected final A mappingAnnotation;
+
+
+ protected AbstractJavaTypeMapping(JavaPersistentType parent, A mappingAnnotation) {
+ super(parent);
+ this.mappingAnnotation = mappingAnnotation;
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaPersistentType getParent() {
+ return (JavaPersistentType) super.getParent();
+ }
+
+ public JavaPersistentType getPersistentType() {
+ return this.getParent();
+ }
+
+ public JavaResourcePersistentType getResourcePersistentType() {
+ return this.getPersistentType().getResourcePersistentType();
+ }
+
+ public String getName() {
+ return this.getPersistentType().getName();
+ }
+
+ public A getMappingAnnotation() {
+ return this.mappingAnnotation;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.getPersistentType().getName());
+ }
+
+
+ // ********** tables **********
+
+ public String getPrimaryTableName() {
+ return null;
+ }
+
+ public org.eclipse.jpt.jpa.db.Table getPrimaryDbTable() {
+ return null;
+ }
+
+ public Schema getDbSchema() {
+ return null;
+ }
+
+ public Iterator<ReadOnlyTable> associatedTables() {
+ return EmptyIterator.instance();
+ }
+
+ public Iterator<ReadOnlyTable> allAssociatedTables() {
+ return EmptyIterator.instance();
+ }
+
+ public Iterator<String> allAssociatedTableNames() {
+ return EmptyIterator.instance();
+ }
+
+ public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) {
+ return null;
+ }
+
+
+ // ********** inheritance **********
+
+ public TypeMapping getSuperTypeMapping() {
+ PersistentType superPersistentType = this.getPersistentType().getSuperPersistentType();
+ return (superPersistentType == null) ? null : superPersistentType.getMapping();
+ }
+
+ public Iterator<TypeMapping> inheritanceHierarchy() {
+ return this.convertToMappings(this.getPersistentType().inheritanceHierarchy());
+ }
+
+ protected Iterable<TypeMapping> getInheritanceHierarchy() {
+ return CollectionTools.iterable(this.inheritanceHierarchy());
+ }
+
+ /**
+ * Return the type mapping's "persistence" ancestors,
+ * <em>excluding</em> the type mapping itself.
+ * The returned iterator will return elements infinitely if the hierarchy
+ * has a loop.
+ */
+ protected Iterator<TypeMapping> ancestors() {
+ return this.convertToMappings(this.getPersistentType().ancestors());
+ }
+
+ protected Iterable<TypeMapping> getAncestors() {
+ return CollectionTools.iterable(this.ancestors());
+ }
+
+ protected Iterator<TypeMapping> convertToMappings(Iterator<PersistentType> types) {
+ return new TransformationIterator<PersistentType, TypeMapping>(types) {
+ @Override
+ protected TypeMapping transform(PersistentType type) {
+ return type.getMapping();
+ }
+ };
+ }
+
+
+ // ********** attribute mappings **********
+
+ public Iterator<JavaAttributeMapping> attributeMappings() {
+ return new TransformationIterator<JavaPersistentAttribute, JavaAttributeMapping>(this.getPersistentType().attributes()) {
+ @Override
+ protected JavaAttributeMapping transform(JavaPersistentAttribute attribute) {
+ return attribute.getMapping();
+ }
+ };
+ }
+
+ public Iterable<JavaAttributeMapping> getAttributeMappings(final String mappingKey) {
+ return new FilteringIterable<JavaAttributeMapping>(CollectionTools.collection(this.attributeMappings())) {
+ @Override
+ protected boolean accept(JavaAttributeMapping o) {
+ return Tools.valuesAreEqual(o.getKey(), mappingKey);
+ }
+ };
+ }
+
+ public Iterator<AttributeMapping> allAttributeMappings() {
+ return new CompositeIterator<AttributeMapping>(this.allAttributeMappingsLists());
+ }
+
+ protected Iterator<Iterator<AttributeMapping>> allAttributeMappingsLists() {
+ return new TransformationIterator<TypeMapping, Iterator<AttributeMapping>>(this.nonNullInheritanceHierarchy(), TypeMappingTools.ATTRIBUTE_MAPPINGS_TRANSFORMER);
+ }
+
+ protected Iterator<TypeMapping> nonNullInheritanceHierarchy() {
+ return new FilteringIterator<TypeMapping>(this.inheritanceHierarchy(), NotNullFilter.<TypeMapping>instance());
+ }
+
+ public Iterable<AttributeMapping> getAllAttributeMappings(final String mappingKey) {
+ return new FilteringIterable<AttributeMapping>(CollectionTools.collection(this.allAttributeMappings())) {
+ @Override
+ protected boolean accept(AttributeMapping o) {
+ return Tools.valuesAreEqual(o.getKey(), mappingKey);
+ }
+ };
+ }
+
+ public boolean attributeMappingKeyAllowed(String attributeMappingKey) {
+ return true;
+ }
+
+
+ // ********** attribute overrides **********
+
+ public Iterator<String> overridableAttributeNames() {
+ return new CompositeIterator<String>(this.overridableAttributeNamesLists());
+ }
+
+ protected Iterator<Iterator<String>> overridableAttributeNamesLists() {
+ return new TransformationIterator<AttributeMapping, Iterator<String>>(this.attributeMappings(), AttributeMappingTools.ALL_OVERRIDABLE_ATTRIBUTE_MAPPING_NAMES_TRANSFORMER);
+ }
+
+ public Iterator<String> allOverridableAttributeNames() {
+ return new CompositeIterator<String>(this.allOverridableAttributeNamesLists());
+ }
+
+ protected Iterator<Iterator<String>> allOverridableAttributeNamesLists() {
+ return new TransformationIterator<TypeMapping, Iterator<String>>(this.inheritanceHierarchy(), TypeMappingTools.OVERRIDABLE_ATTRIBUTE_NAMES_TRANSFORMER);
+ }
+
+ public Column resolveOverriddenColumn(String attributeName) {
+ for (AttributeMapping attributeMapping : CollectionTools.iterable(this.attributeMappings())) {
+ Column column = attributeMapping.resolveOverriddenColumn(attributeName);
+ if (column != null) {
+ return column;
+ }
+ }
+ return null;
+ }
+
+
+ // ********** association overrides **********
+
+ public Iterator<String> overridableAssociationNames() {
+ return new CompositeIterator<String>(this.overridableAssociationNamesLists());
+ }
+
+ protected Iterator<Iterator<String>> overridableAssociationNamesLists() {
+ return new TransformationIterator<AttributeMapping, Iterator<String>>(this.attributeMappings(), AttributeMappingTools.ALL_OVERRIDABLE_ASSOCIATION_MAPPING_NAMES_TRANSFORMER);
+ }
+
+ public Iterator<String> allOverridableAssociationNames() {
+ return new CompositeIterator<String>(this.allOverridableAssociationNamesLists());
+ }
+
+ protected Iterator<Iterator<String>> allOverridableAssociationNamesLists() {
+ return new TransformationIterator<TypeMapping, Iterator<String>>(this.inheritanceHierarchy(), TypeMappingTools.OVERRIDABLE_ASSOCIATION_NAMES_TRANSFORMER);
+ }
+
+ public Relationship resolveOverriddenRelationship(String attributeName) {
+ for (AttributeMapping attributeMapping : CollectionTools.iterable(this.attributeMappings())) {
+ Relationship relationship = attributeMapping.resolveOverriddenRelationship(attributeName);
+ if (relationship != null) {
+ return relationship;
+ }
+ }
+ return null;
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.validateType(messages, reporter, astRoot);
+ }
+
+ protected void validateType(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ this.buildTypeMappingValidator(astRoot).validate(messages, reporter);
+ }
+
+ protected JptValidator buildTypeMappingValidator(CompilationUnit astRoot) {
+ return new GenericTypeMappingValidator(this, this.getResourcePersistentType(), buildTextRangeResolver(astRoot));
+ }
+
+ protected TypeMappingTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
+ return new JavaTypeMappingTextRangeResolver(this, astRoot);
+ }
+
+ public boolean validatesAgainstDatabase() {
+ return this.getPersistenceUnit().validatesAgainstDatabase();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ TextRange textRange = this.mappingAnnotation.getTextRange(astRoot);
+ return (textRange != null) ? textRange : this.getPersistentType().getValidationTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMapping.java
new file mode 100644
index 0000000000..b88646d9e0
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMapping.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.Association;
+import org.eclipse.jpt.common.utility.internal.SimpleAssociation;
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Converter;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaTemporalConverter;
+import org.eclipse.jpt.jpa.core.context.java.JavaVersionMapping;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.NamedColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaConverter;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.VersionAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java version mapping
+ */
+public abstract class AbstractJavaVersionMapping
+ extends AbstractJavaAttributeMapping<VersionAnnotation>
+ implements JavaVersionMapping
+{
+ protected final JavaColumn column;
+
+ protected JavaConverter converter; // never null
+
+
+ // the spec does not list Temporal explicitly,
+ // but it is included in the orm.xml schema...
+ protected static final JavaConverter.Adapter[] CONVERTER_ADAPTER_ARRAY = new JavaConverter.Adapter[] {
+ JavaTemporalConverter.Adapter.instance(),
+ };
+ protected static final Iterable<JavaConverter.Adapter> CONVERTER_ADAPTERS = new ArrayIterable<JavaConverter.Adapter>(CONVERTER_ADAPTER_ARRAY);
+
+
+ protected AbstractJavaVersionMapping(JavaPersistentAttribute parent) {
+ super(parent);
+ this.column = this.buildColumn();
+ this.converter = this.buildConverter();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.column.synchronizeWithResourceModel();
+ this.syncConverter();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.column.update();
+ this.converter.update();
+ }
+
+
+ // ********** column **********
+
+ public JavaColumn getColumn() {
+ return this.column;
+ }
+
+ protected JavaColumn buildColumn() {
+ return this.getJpaFactory().buildJavaColumn(this, this);
+ }
+
+
+ // ********** converter **********
+
+ public JavaConverter getConverter() {
+ return this.converter;
+ }
+
+ public void setConverter(Class<? extends Converter> converterType) {
+ if (this.converter.getType() != converterType) {
+ this.converter.dispose();
+ JavaConverter.Adapter converterAdapter = this.getConverterAdapter(converterType);
+ this.retainConverterAnnotation(converterAdapter);
+ this.setConverter_(this.buildConverter(converterAdapter));
+ }
+ }
+
+ protected JavaConverter buildConverter(JavaConverter.Adapter converterAdapter) {
+ return (converterAdapter != null) ?
+ converterAdapter.buildNewConverter(this, this.getJpaFactory()) :
+ this.buildNullConverter();
+ }
+
+ protected void setConverter_(JavaConverter converter) {
+ Converter old = this.converter;
+ this.converter = converter;
+ this.firePropertyChanged(CONVERTER_PROPERTY, old, converter);
+ }
+
+ /**
+ * Clear all the converter annotations <em>except</em> for the annotation
+ * corresponding to the specified adapter. If the specified adapter is
+ * <code>null</code>, remove <em>all</em> the converter annotations.
+ */
+ protected void retainConverterAnnotation(JavaConverter.Adapter converterAdapter) {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter != converterAdapter) {
+ adapter.removeConverterAnnotation(resourceAttribute);
+ }
+ }
+ }
+
+ protected JavaConverter buildConverter() {
+ JpaFactory jpaFactory = this.getJpaFactory();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ JavaConverter javaConverter = adapter.buildConverter(this, jpaFactory);
+ if (javaConverter != null) {
+ return javaConverter;
+ }
+ }
+ return this.buildNullConverter();
+ }
+
+ protected void syncConverter() {
+ Association<JavaConverter.Adapter, Annotation> assoc = this.getConverterAnnotation();
+ if (assoc == null) {
+ if (this.converter.getType() != null) {
+ this.setConverter_(this.buildNullConverter());
+ }
+ } else {
+ JavaConverter.Adapter adapter = assoc.getKey();
+ Annotation annotation = assoc.getValue();
+ if ((this.converter.getType() == adapter.getConverterType()) &&
+ (this.converter.getConverterAnnotation() == annotation)) {
+ this.converter.synchronizeWithResourceModel();
+ } else {
+ this.setConverter_(adapter.buildConverter(annotation, this, this.getJpaFactory()));
+ }
+ }
+ }
+
+ /**
+ * Return the first converter annotation we find along with its corresponding
+ * adapter. Return <code>null</code> if there are no converter annotations.
+ */
+ protected Association<JavaConverter.Adapter, Annotation> getConverterAnnotation() {
+ JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute();
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ Annotation annotation = adapter.getConverterAnnotation(resourceAttribute);
+ if (annotation != null) {
+ return new SimpleAssociation<JavaConverter.Adapter, Annotation>(adapter, annotation);
+ }
+ }
+ return null;
+ }
+
+ protected JavaConverter buildNullConverter() {
+ return new NullJavaConverter(this);
+ }
+
+
+ // ********** converter adapters **********
+
+ /**
+ * Return the converter adapter for the specified converter type.
+ */
+ protected JavaConverter.Adapter getConverterAdapter(Class<? extends Converter> converterType) {
+ for (JavaConverter.Adapter adapter : this.getConverterAdapters()) {
+ if (adapter.getConverterType() == converterType) {
+ return adapter;
+ }
+ }
+ return null;
+ }
+
+ protected Iterable<JavaConverter.Adapter> getConverterAdapters() {
+ return CONVERTER_ADAPTERS;
+ }
+
+
+ // ********** misc **********
+
+ public String getKey() {
+ return MappingKeys.VERSION_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ @Override
+ protected String getAnnotationName() {
+ return VersionAnnotation.ANNOTATION_NAME;
+ }
+
+
+ // ********** JavaColumn.Owner implementation **********
+
+ public ColumnAnnotation getColumnAnnotation() {
+ return (ColumnAnnotation) this.getResourcePersistentAttribute().getNonNullAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public void removeColumnAnnotation() {
+ this.getResourcePersistentAttribute().removeAnnotation(ColumnAnnotation.ANNOTATION_NAME);
+ }
+
+ public String getDefaultColumnName() {
+ return this.getName();
+ }
+
+ public String getDefaultTableName() {
+ return this.getTypeMapping().getPrimaryTableName();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return this.getTypeMapping().allAssociatedTableNames();
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new NamedColumnValidator((BaseColumn) column, (BaseColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider());
+ }
+
+
+ // ********** 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.column.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+ result = this.converter.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.column.validate(messages, reporter, astRoot);
+ this.converter.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMappingDefinition.java
new file mode 100644
index 0000000000..5c62ad3ecc
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVersionMappingDefinition.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TemporalAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.VersionAnnotation;
+
+public abstract class AbstractJavaVersionMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ protected AbstractJavaVersionMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.VERSION_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return VersionAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ ColumnAnnotation.ANNOTATION_NAME,
+ TemporalAnnotation.ANNOTATION_NAME,
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaVersionMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualBaseColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualBaseColumn.java
new file mode 100644
index 0000000000..a28099d901
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualBaseColumn.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyNamedColumn;
+import org.eclipse.jpt.jpa.core.context.VirtualBaseColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+
+public abstract class AbstractJavaVirtualBaseColumn<O extends ReadOnlyNamedColumn.Owner, C extends BaseColumn>
+ extends AbstractJavaVirtualNamedColumn<O, C>
+ implements VirtualBaseColumn
+{
+ protected String specifiedTable;
+ protected String defaultTable;
+
+ protected Boolean specifiedUnique;
+ protected boolean defaultUnique;
+
+ protected Boolean specifiedNullable;
+ protected boolean defaultNullable;
+
+ protected Boolean specifiedInsertable;
+ protected boolean defaultInsertable;
+
+ protected Boolean specifiedUpdatable;
+ protected boolean defaultUpdatable;
+
+
+ protected AbstractJavaVirtualBaseColumn(JavaJpaContextNode parent, O owner) {
+ super(parent, owner);
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+
+ this.setSpecifiedTable(this.buildSpecifiedTable());
+ this.setDefaultTable(this.buildDefaultTable());
+
+ this.setSpecifiedUnique(this.buildSpecifiedUnique());
+ this.setDefaultUnique(this.buildDefaultUnique());
+
+ this.setSpecifiedNullable(this.buildSpecifiedNullable());
+ this.setDefaultNullable(this.buildDefaultNullable());
+
+ this.setSpecifiedInsertable(this.buildSpecifiedInsertable());
+ this.setDefaultInsertable(this.buildDefaultInsertable());
+
+ this.setSpecifiedUpdatable(this.buildSpecifiedUpdatable());
+ this.setDefaultUpdatable(this.buildDefaultUpdatable());
+ }
+
+
+ // ********** table **********
+
+ public String getTable() {
+ return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable;
+ }
+
+ public String getSpecifiedTable() {
+ return this.specifiedTable;
+ }
+
+ protected void setSpecifiedTable(String table) {
+ String old = this.specifiedTable;
+ this.specifiedTable = table;
+ this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table);
+ }
+
+ protected String buildSpecifiedTable() {
+ return this.getOverriddenColumn().getSpecifiedTable();
+ }
+
+ 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);
+ }
+
+ protected String buildDefaultTable() {
+ return this.owner.getDefaultTableName();
+ }
+
+
+ // ********** unique **********
+
+ public boolean isUnique() {
+ return (this.specifiedUnique != null) ? this.specifiedUnique.booleanValue() : this.isDefaultUnique();
+ }
+
+ public Boolean getSpecifiedUnique() {
+ return this.specifiedUnique;
+ }
+
+ protected void setSpecifiedUnique(Boolean unique) {
+ Boolean old = this.specifiedUnique;
+ this.specifiedUnique = unique;
+ this.firePropertyChanged(SPECIFIED_UNIQUE_PROPERTY, old, unique);
+ }
+
+ protected Boolean buildSpecifiedUnique() {
+ return this.getOverriddenColumn().getSpecifiedUnique();
+ }
+
+ public boolean isDefaultUnique() {
+ return this.defaultUnique;
+ }
+
+ protected void setDefaultUnique(boolean unique) {
+ boolean old = this.defaultUnique;
+ this.defaultUnique = unique;
+ this.firePropertyChanged(DEFAULT_UNIQUE_PROPERTY, old, unique);
+ }
+
+ protected boolean buildDefaultUnique() {
+ return DEFAULT_UNIQUE;
+ }
+
+
+ // ********** nullable **********
+
+ public boolean isNullable() {
+ return (this.specifiedNullable != null) ? this.specifiedNullable.booleanValue() : this.isDefaultNullable();
+ }
+
+ public Boolean getSpecifiedNullable() {
+ return this.specifiedNullable;
+ }
+
+ protected void setSpecifiedNullable(Boolean nullable) {
+ Boolean old = this.specifiedNullable;
+ this.specifiedNullable = nullable;
+ this.firePropertyChanged(SPECIFIED_NULLABLE_PROPERTY, old, nullable);
+ }
+
+ protected Boolean buildSpecifiedNullable() {
+ return this.getOverriddenColumn().getSpecifiedNullable();
+ }
+
+ public boolean isDefaultNullable() {
+ return this.defaultNullable;
+ }
+
+ protected void setDefaultNullable(boolean nullable) {
+ boolean old = this.defaultNullable;
+ this.defaultNullable = nullable;
+ this.firePropertyChanged(DEFAULT_NULLABLE_PROPERTY, old, nullable);
+ }
+
+ protected boolean buildDefaultNullable() {
+ return DEFAULT_NULLABLE;
+ }
+
+
+ // ********** insertable **********
+
+ public boolean isInsertable() {
+ return (this.specifiedInsertable != null) ? this.specifiedInsertable.booleanValue() : this.isDefaultInsertable();
+ }
+
+ public Boolean getSpecifiedInsertable() {
+ return this.specifiedInsertable;
+ }
+
+ protected void setSpecifiedInsertable(Boolean insertable) {
+ Boolean old = this.specifiedInsertable;
+ this.specifiedInsertable = insertable;
+ this.firePropertyChanged(SPECIFIED_INSERTABLE_PROPERTY, old, insertable);
+ }
+
+ protected Boolean buildSpecifiedInsertable() {
+ return this.getOverriddenColumn().getSpecifiedInsertable();
+ }
+
+ public boolean isDefaultInsertable() {
+ return this.defaultInsertable;
+ }
+
+ protected void setDefaultInsertable(boolean insertable) {
+ boolean old = this.defaultInsertable;
+ this.defaultInsertable = insertable;
+ this.firePropertyChanged(DEFAULT_INSERTABLE_PROPERTY, old, insertable);
+ }
+
+ protected boolean buildDefaultInsertable() {
+ return DEFAULT_INSERTABLE;
+ }
+
+
+ // ********** updatable **********
+
+ public boolean isUpdatable() {
+ return (this.specifiedUpdatable != null) ? this.specifiedUpdatable.booleanValue() : this.isDefaultUpdatable();
+ }
+
+ public Boolean getSpecifiedUpdatable() {
+ return this.specifiedUpdatable;
+ }
+
+ protected void setSpecifiedUpdatable(Boolean updatable) {
+ Boolean old = this.specifiedUpdatable;
+ this.specifiedUpdatable = updatable;
+ this.firePropertyChanged(SPECIFIED_UPDATABLE_PROPERTY, old, updatable);
+ }
+
+ protected Boolean buildSpecifiedUpdatable() {
+ return this.getOverriddenColumn().getSpecifiedUpdatable();
+ }
+
+ public boolean isDefaultUpdatable() {
+ return this.defaultUpdatable;
+ }
+
+ protected void setDefaultUpdatable(boolean updatable) {
+ boolean old = this.defaultUpdatable;
+ this.defaultUpdatable = updatable;
+ this.firePropertyChanged(DEFAULT_UPDATABLE_PROPERTY, old, updatable);
+ }
+
+ protected boolean buildDefaultUpdatable() {
+ return DEFAULT_UPDATABLE;
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualNamedColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualNamedColumn.java
new file mode 100644
index 0000000000..517dbeab97
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualNamedColumn.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyNamedColumn;
+import org.eclipse.jpt.jpa.core.context.VirtualNamedColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+
+/**
+ * Java virtual<ul>
+ * <li>column
+ * <li>join column
+ * </ul>
+ * <strong>NB:</strong> all state is sync'ed/updated in {@link #update()}
+ * because <em>all</em> of its derived from the context model (i.e. none of it
+ * is derived from the resource model).
+ */
+public abstract class AbstractJavaVirtualNamedColumn<O extends ReadOnlyNamedColumn.Owner, C extends NamedColumn>
+ extends AbstractJavaJpaContextNode
+ implements VirtualNamedColumn
+{
+ protected final O owner;
+
+ protected String specifiedName;
+ protected String defaultName;
+
+ protected String columnDefinition;
+
+
+ protected AbstractJavaVirtualNamedColumn(JavaJpaContextNode parent, O owner) {
+ super(parent);
+ this.owner = owner;
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+
+ this.setSpecifiedName(this.buildSpecifiedName());
+ this.setDefaultName(this.buildDefaultName());
+
+ this.setColumnDefinition(this.buildColumnDefinition());
+ }
+
+
+ // ********** column **********
+
+ /**
+ * This should never return <code>null</code>.
+ */
+ public abstract C getOverriddenColumn();
+
+
+ // ********** name **********
+
+ public String getName() {
+ return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
+ }
+
+ public String getSpecifiedName() {
+ return this.specifiedName;
+ }
+
+ protected void setSpecifiedName(String name) {
+ String old = this.specifiedName;
+ this.specifiedName = name;
+ this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildSpecifiedName() {
+ return this.getOverriddenColumn().getSpecifiedName();
+ }
+
+ public String getDefaultName() {
+ return this.defaultName;
+ }
+
+ protected void setDefaultName(String name) {
+ String old = this.defaultName;
+ this.defaultName = name;
+ this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildDefaultName() {
+ return this.owner.getDefaultColumnName();
+ }
+
+
+ // ********** column definition **********
+
+ public String getColumnDefinition() {
+ return this.columnDefinition;
+ }
+
+ protected void setColumnDefinition(String columnDefinition) {
+ String old = this.columnDefinition;
+ this.columnDefinition = columnDefinition;
+ this.firePropertyChanged(COLUMN_DEFINITION_PROPERTY, old, columnDefinition);
+ }
+
+ protected String buildColumnDefinition() {
+ return this.getOverriddenColumn().getColumnDefinition();
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return null; // not sure this column is validated...
+ }
+
+
+ // ********** misc **********
+
+ public boolean isVirtual() {
+ return true;
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ String table = this.getTable();
+ if (table != null) {
+ sb.append(table);
+ sb.append('.');
+ }
+ sb.append(this.getName());
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualOverride.java
new file mode 100644
index 0000000000..6f589efad7
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualOverride.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverride;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverride;
+
+/**
+ * Virtual Java override
+ */
+public abstract class AbstractJavaVirtualOverride<C extends JavaOverrideContainer>
+ extends AbstractJavaJpaContextNode
+ implements JavaVirtualOverride
+{
+ protected final String name; // never null
+
+
+ protected AbstractJavaVirtualOverride(C parent, String name) {
+ super(parent);
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public boolean isVirtual() {
+ return true;
+ }
+
+ public JavaOverride convertToSpecified() {
+ return this.getContainer().convertOverrideToSpecified(this);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public C getParent() {
+ return (C) super.getParent();
+ }
+
+ public C getContainer() {
+ return this.getParent();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getParent().getValidationTextRange(astRoot);
+ }
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.name);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualReferenceTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualReferenceTable.java
new file mode 100644
index 0000000000..ec4d5b507f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualReferenceTable.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.ListIterator;
+import java.util.Vector;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SingleElementListIterable;
+import org.eclipse.jpt.jpa.core.context.JoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReferenceTable;
+import org.eclipse.jpt.jpa.core.context.VirtualReferenceTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumn;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+
+public abstract class AbstractJavaVirtualReferenceTable<T extends ReferenceTable>
+ extends AbstractJavaVirtualTable<T>
+ implements VirtualReferenceTable
+{
+ protected final Vector<JavaVirtualJoinColumn> specifiedJoinColumns = new Vector<JavaVirtualJoinColumn>();
+ protected final SpecifiedJoinColumnContainerAdapter specifiedJoinColumnContainerAdapter = new SpecifiedJoinColumnContainerAdapter();
+ protected final ReadOnlyJoinColumn.Owner joinColumnOwner;
+
+ protected JavaVirtualJoinColumn defaultJoinColumn;
+
+
+ protected AbstractJavaVirtualReferenceTable(JavaJpaContextNode parent) {
+ super(parent);
+ this.joinColumnOwner = this.buildJoinColumnOwner();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateSpecifiedJoinColumns();
+ this.updateDefaultJoinColumn();
+ }
+
+
+ // ********** join columns **********
+
+ public ListIterator<JavaVirtualJoinColumn> joinColumns() {
+ return this.getJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getJoinColumns() {
+ return this.hasSpecifiedJoinColumns() ? this.getSpecifiedJoinColumns() : this.getDefaultJoinColumns();
+ }
+
+ public int joinColumnsSize() {
+ return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumnsSize() : this.getDefaultJoinColumnsSize();
+ }
+
+
+ // ********** specified join columns **********
+
+ public ListIterator<JavaVirtualJoinColumn> specifiedJoinColumns() {
+ return this.getSpecifiedJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getSpecifiedJoinColumns() {
+ return new LiveCloneListIterable<JavaVirtualJoinColumn>(this.specifiedJoinColumns);
+ }
+
+ public int specifiedJoinColumnsSize() {
+ return this.specifiedJoinColumns.size();
+ }
+
+ public boolean hasSpecifiedJoinColumns() {
+ return this.specifiedJoinColumns.size() != 0;
+ }
+
+ public JavaVirtualJoinColumn getSpecifiedJoinColumn(int index) {
+ return this.specifiedJoinColumns.get(index);
+ }
+
+ protected void updateSpecifiedJoinColumns() {
+ ContextContainerTools.update(this.specifiedJoinColumnContainerAdapter);
+ }
+
+ protected Iterable<JoinColumn> getOverriddenJoinColumns() {
+ return CollectionTools.iterable(this.getOverriddenTable().specifiedJoinColumns());
+ }
+
+ protected void moveSpecifiedJoinColumn(int index, JavaVirtualJoinColumn joinColumn) {
+ this.moveItemInList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ }
+
+ protected JavaVirtualJoinColumn addSpecifiedJoinColumn(int index, JoinColumn joinColumn) {
+ JavaVirtualJoinColumn virtualJoinColumn = this.buildJoinColumn(joinColumn);
+ this.addItemToList(index, virtualJoinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ return virtualJoinColumn;
+ }
+
+ protected void removeSpecifiedJoinColumn(JavaVirtualJoinColumn joinColumn) {
+ this.removeItemFromList(joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST);
+ }
+
+ /**
+ * specified join column container adapter
+ */
+ protected class SpecifiedJoinColumnContainerAdapter
+ implements ContextContainerTools.Adapter<JavaVirtualJoinColumn, JoinColumn>
+ {
+ public Iterable<JavaVirtualJoinColumn> getContextElements() {
+ return AbstractJavaVirtualReferenceTable.this.getSpecifiedJoinColumns();
+ }
+ public Iterable<JoinColumn> getResourceElements() {
+ return AbstractJavaVirtualReferenceTable.this.getOverriddenJoinColumns();
+ }
+ public JoinColumn getResourceElement(JavaVirtualJoinColumn contextElement) {
+ return contextElement.getOverriddenColumn();
+ }
+ public void moveContextElement(int index, JavaVirtualJoinColumn element) {
+ AbstractJavaVirtualReferenceTable.this.moveSpecifiedJoinColumn(index, element);
+ }
+ public void addContextElement(int index, JoinColumn element) {
+ AbstractJavaVirtualReferenceTable.this.addSpecifiedJoinColumn(index, element);
+ }
+ public void removeContextElement(JavaVirtualJoinColumn element) {
+ AbstractJavaVirtualReferenceTable.this.removeSpecifiedJoinColumn(element);
+ }
+ }
+
+
+ // ********** default join column **********
+
+ public JavaVirtualJoinColumn getDefaultJoinColumn() {
+ return this.defaultJoinColumn;
+ }
+
+ protected void setDefaultJoinColumn(JavaVirtualJoinColumn joinColumn) {
+ JavaVirtualJoinColumn old = this.defaultJoinColumn;
+ this.defaultJoinColumn = joinColumn;
+ this.firePropertyChanged(DEFAULT_JOIN_COLUMN_PROPERTY, old, joinColumn);
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getDefaultJoinColumns() {
+ return (this.defaultJoinColumn != null) ?
+ new SingleElementListIterable<JavaVirtualJoinColumn>(this.defaultJoinColumn) :
+ EmptyListIterable.<JavaVirtualJoinColumn>instance();
+ }
+
+ protected int getDefaultJoinColumnsSize() {
+ return (this.defaultJoinColumn == null) ? 0 : 1;
+ }
+
+ protected void updateDefaultJoinColumn() {
+ if (this.buildsDefaultJoinColumn()) {
+ if (this.defaultJoinColumn == null) {
+ this.setDefaultJoinColumn(this.buildJoinColumn(this.getOverriddenTable().getDefaultJoinColumn()));
+ } else {
+ this.defaultJoinColumn.update();
+ }
+ } else {
+ this.setDefaultJoinColumn(null);
+ }
+ }
+
+ protected boolean buildsDefaultJoinColumn() {
+ return ! this.hasSpecifiedJoinColumns();
+ }
+
+
+ // ********** misc **********
+
+ protected JavaVirtualJoinColumn buildJoinColumn(JoinColumn joinColumn) {
+ return this.buildJoinColumn(this.joinColumnOwner, joinColumn);
+ }
+
+ protected JavaVirtualJoinColumn buildJoinColumn(ReadOnlyJoinColumn.Owner owner, JoinColumn joinColumn) {
+ return this.getJpaFactory().buildJavaVirtualJoinColumn(this, owner, joinColumn);
+ }
+
+ protected abstract ReadOnlyJoinColumn.Owner buildJoinColumnOwner();
+
+ @Override
+ protected String buildDefaultSchema() {
+ return this.getContextDefaultSchema();
+ }
+
+ @Override
+ protected String buildDefaultCatalog() {
+ return this.getContextDefaultCatalog();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualTable.java
new file mode 100644
index 0000000000..466112abe3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/AbstractJavaVirtualTable.java
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.ListIterator;
+import java.util.Vector;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.NameTools;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.jpa.core.context.Table;
+import org.eclipse.jpt.jpa.core.context.UniqueConstraint;
+import org.eclipse.jpt.jpa.core.context.VirtualTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualUniqueConstraint;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.db.Catalog;
+import org.eclipse.jpt.jpa.db.Schema;
+import org.eclipse.jpt.jpa.db.SchemaContainer;
+
+public abstract class AbstractJavaVirtualTable<T extends Table>
+ extends AbstractJavaJpaContextNode
+ implements VirtualTable
+{
+ protected String specifiedName;
+ protected String defaultName;
+
+ protected String specifiedSchema;
+ protected String defaultSchema;
+
+ protected String specifiedCatalog;
+ protected String defaultCatalog;
+
+ protected final Vector<JavaVirtualUniqueConstraint> uniqueConstraints = new Vector<JavaVirtualUniqueConstraint>();
+ protected final UniqueConstraintContainerAdapter uniqueConstraintContainerAdapter = new UniqueConstraintContainerAdapter();
+
+
+ protected AbstractJavaVirtualTable(JavaJpaContextNode parent) {
+ super(parent);
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+
+ this.setSpecifiedName(this.buildSpecifiedName());
+ this.setDefaultName(this.buildDefaultName());
+
+ this.setSpecifiedSchema(this.buildSpecifiedSchema());
+ this.setDefaultSchema(this.buildDefaultSchema());
+
+ this.setSpecifiedCatalog(this.buildSpecifiedCatalog());
+ this.setDefaultCatalog(this.buildDefaultCatalog());
+
+ this.updateUniqueConstraints();
+ }
+
+
+ // ********** table **********
+
+ /**
+ * This should never return <code>null</code>.
+ */
+ public abstract T getOverriddenTable();
+
+
+ // ********** name **********
+
+ public String getName() {
+ return (this.specifiedName != null) ? this.specifiedName : this.defaultName;
+ }
+
+ public String getSpecifiedName() {
+ return this.specifiedName;
+ }
+
+ protected void setSpecifiedName(String name) {
+ String old = this.specifiedName;
+ this.specifiedName = name;
+ this.firePropertyChanged(SPECIFIED_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildSpecifiedName() {
+ return this.getOverriddenTable().getSpecifiedName();
+ }
+
+ public String getDefaultName() {
+ return this.defaultName;
+ }
+
+ protected void setDefaultName(String name) {
+ String old = this.defaultName;
+ this.defaultName = name;
+ this.firePropertyChanged(DEFAULT_NAME_PROPERTY, old, name);
+ }
+
+ protected abstract String buildDefaultName();
+
+
+ // ********** schema **********
+
+ public String getSchema() {
+ return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema;
+ }
+
+ public String getSpecifiedSchema() {
+ return this.specifiedSchema;
+ }
+
+ protected void setSpecifiedSchema(String schema) {
+ String old = this.specifiedSchema;
+ this.specifiedSchema = schema;
+ this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema);
+ }
+
+ protected String buildSpecifiedSchema() {
+ return this.getOverriddenTable().getSchema();
+ }
+
+ 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);
+ }
+
+ protected abstract String buildDefaultSchema();
+
+
+ // ********** catalog **********
+
+ public String getCatalog() {
+ return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog;
+ }
+
+ public String getSpecifiedCatalog() {
+ return this.specifiedCatalog;
+ }
+
+ protected void setSpecifiedCatalog(String catalog) {
+ String old = this.specifiedCatalog;
+ this.specifiedCatalog = catalog;
+ this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog);
+ }
+
+ protected String buildSpecifiedCatalog() {
+ return this.getOverriddenTable().getCatalog();
+ }
+
+ 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);
+ }
+
+ protected abstract String buildDefaultCatalog();
+
+
+ // ********** unique constraints **********
+
+ public ListIterator<JavaVirtualUniqueConstraint> uniqueConstraints() {
+ return this.getUniqueConstraints().iterator();
+ }
+
+ protected ListIterable<JavaVirtualUniqueConstraint> getUniqueConstraints() {
+ return new LiveCloneListIterable<JavaVirtualUniqueConstraint>(this.uniqueConstraints);
+ }
+
+ public int uniqueConstraintsSize() {
+ return this.uniqueConstraints.size();
+ }
+
+ public JavaVirtualUniqueConstraint getUniqueConstraint(int index) {
+ return this.uniqueConstraints.get(index);
+ }
+
+ protected void updateUniqueConstraints() {
+ ContextContainerTools.update(this.uniqueConstraintContainerAdapter);
+ }
+
+ protected Iterable<UniqueConstraint> getOverriddenUniqueConstraints() {
+ return CollectionTools.iterable(this.getOverriddenTable().uniqueConstraints());
+ }
+
+ protected void moveUniqueConstraint(int index, JavaVirtualUniqueConstraint constraint) {
+ this.moveItemInList(index, constraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ }
+
+ protected JavaVirtualUniqueConstraint addUniqueConstraint(int index, UniqueConstraint uniqueConstraint) {
+ JavaVirtualUniqueConstraint virtualConstraint = this.buildUniqueConstraint(uniqueConstraint);
+ this.addItemToList(index, virtualConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ return virtualConstraint;
+ }
+
+ protected JavaVirtualUniqueConstraint buildUniqueConstraint(UniqueConstraint uniqueConstraint) {
+ return this.getJpaFactory().buildJavaVirtualUniqueConstraint(this, uniqueConstraint);
+ }
+
+ protected void removeUniqueConstraint(JavaVirtualUniqueConstraint constraint) {
+ this.removeItemFromList(constraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST);
+ }
+
+ /**
+ * unique constraint container adapter
+ */
+ protected class UniqueConstraintContainerAdapter
+ implements ContextContainerTools.Adapter<JavaVirtualUniqueConstraint, UniqueConstraint>
+ {
+ public Iterable<JavaVirtualUniqueConstraint> getContextElements() {
+ return AbstractJavaVirtualTable.this.getUniqueConstraints();
+ }
+ public Iterable<UniqueConstraint> getResourceElements() {
+ return AbstractJavaVirtualTable.this.getOverriddenUniqueConstraints();
+ }
+ public UniqueConstraint getResourceElement(JavaVirtualUniqueConstraint contextElement) {
+ return contextElement.getOverriddenUniqueConstraint();
+ }
+ public void moveContextElement(int index, JavaVirtualUniqueConstraint element) {
+ AbstractJavaVirtualTable.this.moveUniqueConstraint(index, element);
+ }
+ public void addContextElement(int index, UniqueConstraint resourceElement) {
+ AbstractJavaVirtualTable.this.addUniqueConstraint(index, resourceElement);
+ }
+ public void removeContextElement(JavaVirtualUniqueConstraint element) {
+ AbstractJavaVirtualTable.this.removeUniqueConstraint(element);
+ }
+ }
+
+
+ // ********** database stuff **********
+
+ public org.eclipse.jpt.jpa.db.Table getDbTable() {
+ Schema dbSchema = this.getDbSchema();
+ return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getName());
+ }
+
+ public Schema getDbSchema() {
+ SchemaContainer dbSchemaContainer = this.getDbSchemaContainer();
+ return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema());
+ }
+
+ /**
+ * 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.resolveDbCatalog(catalog) : this.getDatabase();
+ }
+
+ /**
+ * 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.resolveDbCatalog(catalog);
+ }
+
+ protected boolean isResolved() {
+ return this.getDbTable() != null;
+ }
+
+ protected boolean hasResolvedSchema() {
+ return this.getDbSchema() != null;
+ }
+
+ /**
+ * 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.
+ */
+ protected boolean hasResolvedCatalog() {
+ String catalog = this.getCatalog();
+ return (catalog == null) || (this.resolveDbCatalog(catalog) != null);
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return null;
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.buildQualifiedName());
+ }
+
+ protected String buildQualifiedName() {
+ return NameTools.buildQualifiedDatabaseObjectName(this.getCatalog(), this.getSchema(), this.getName());
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaIdClassReference.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaIdClassReference.java
new file mode 100644
index 0000000000..b4a89125dc
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaIdClassReference.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.AccessType;
+import org.eclipse.jpt.jpa.core.context.java.JavaIdClassReference;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.resource.java.IdClassAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
+
+/**
+ * Java ID class reference
+ */
+public class GenericJavaIdClassReference
+ extends AbstractJavaJpaContextNode
+ implements JavaIdClassReference
+{
+ protected String idClassName;
+ protected String fullyQualifiedIdClassName;
+ // the ref holds the type directly because the ref is the type's parent
+ protected JavaPersistentType idClass;
+
+
+ public GenericJavaIdClassReference(JavaTypeMapping parent) {
+ super(parent);
+ this.idClassName = this.buildIdClassName();
+ // 'idClass' is resolved in the update
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setIdClassName_(this.buildIdClassName());
+ if (this.idClass != null) {
+ this.idClass.synchronizeWithResourceModel();
+ }
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.setFullyQualifiedIdClassName(this.buildFullyQualifiedIdClassName());
+ this.updateIdClass();
+ }
+
+
+ // ********** id class name **********
+
+ public String getIdClassName() {
+ return this.getSpecifiedIdClassName();
+ }
+
+ public String getSpecifiedIdClassName() {
+ return this.idClassName;
+ }
+
+ public void setSpecifiedIdClassName(String name) {
+ if (this.valuesAreDifferent(name, this.idClassName)) {
+ this.getIdClassAnnotationForUpdate().setValue(name);
+ this.removeIdClassAnnotationIfUnset();
+ this.setIdClassName_(name);
+ }
+ }
+
+ protected void setIdClassName_(String name) {
+ String old = this.idClassName;
+ this.idClassName = name;
+ this.firePropertyChanged(SPECIFIED_ID_CLASS_NAME_PROPERTY, old, name);
+ }
+
+ protected String buildIdClassName() {
+ IdClassAnnotation annotation = this.getIdClassAnnotation();
+ return (annotation == null) ? null : annotation.getValue();
+ }
+
+ public String getDefaultIdClassName() {
+ return null;
+ }
+
+ public boolean isSpecified() {
+ return this.idClassName != null;
+ }
+
+
+ // ********** id class annotation **********
+
+ /**
+ * Return <code>null</code> if the annotation does not exists.
+ */
+ protected IdClassAnnotation getIdClassAnnotation() {
+ return (IdClassAnnotation) this.getResourcePersistentType().getAnnotation(this.getIdClassAnnotationName());
+ }
+
+ /**
+ * Build the annotation if it does not exist.
+ */
+ protected IdClassAnnotation getIdClassAnnotationForUpdate() {
+ IdClassAnnotation annotation = this.getIdClassAnnotation();
+ return (annotation != null) ? annotation : this.buildIdClassAnnotation();
+ }
+
+ protected IdClassAnnotation buildIdClassAnnotation() {
+ return (IdClassAnnotation) this.getResourcePersistentType().addAnnotation(this.getIdClassAnnotationName());
+ }
+
+ protected void removeIdClassAnnotationIfUnset() {
+ if (this.getIdClassAnnotation().isUnset()) {
+ this.removeIdClassAnnotation();
+ }
+ }
+
+ protected void removeIdClassAnnotation() {
+ this.getResourcePersistentType().removeAnnotation(this.getIdClassAnnotationName());
+ }
+
+ protected String getIdClassAnnotationName() {
+ return IdClassAnnotation.ANNOTATION_NAME;
+ }
+
+
+ // ********** fully-qualified id class name **********
+
+ public String getFullyQualifiedIdClassName() {
+ return this.fullyQualifiedIdClassName;
+ }
+
+ protected void setFullyQualifiedIdClassName(String name) {
+ String old = this.fullyQualifiedIdClassName;
+ this.fullyQualifiedIdClassName = name;
+ this.firePropertyChanged(FULLY_QUALIFIED_ID_CLASS_PROPERTY, old, name);
+ }
+
+ protected String buildFullyQualifiedIdClassName() {
+ IdClassAnnotation annotation = this.getIdClassAnnotation();
+ return (annotation == null) ? null : annotation.getFullyQualifiedClassName();
+ }
+
+
+ // ********** id class **********
+
+ public JavaPersistentType getIdClass() {
+ return this.idClass;
+ }
+
+ protected void setIdClass(JavaPersistentType idClass) {
+ JavaPersistentType old = this.idClass;
+ this.idClass = idClass;
+ this.firePropertyChanged(ID_CLASS_PROPERTY, old, idClass);
+ }
+
+ protected void updateIdClass() {
+ JavaResourcePersistentType resourceIdClass = this.resolveResourceIdClass();
+ if (resourceIdClass == null) {
+ if (this.idClass != null) {
+ this.idClass.dispose();
+ this.setIdClass(null);
+ }
+ } else {
+ if (this.idClass == null) {
+ this.setIdClass(this.buildIdClass(resourceIdClass));
+ } else {
+ if (this.idClass.getResourcePersistentType() == resourceIdClass) {
+ this.idClass.update();
+ } else {
+ this.idClass.dispose();
+ this.setIdClass(this.buildIdClass(resourceIdClass));
+ }
+ }
+ }
+ }
+
+ protected JavaResourcePersistentType resolveResourceIdClass() {
+ return (this.fullyQualifiedIdClassName == null) ?
+ null : this.getJpaProject().getJavaResourcePersistentType(this.fullyQualifiedIdClassName);
+ }
+
+ protected JavaPersistentType buildIdClass(JavaResourcePersistentType resourceClass) {
+ return this.getJpaFactory().buildJavaPersistentType(this, resourceClass);
+ }
+
+ public char getIdClassEnclosingTypeSeparator() {
+ return '.';
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaTypeMapping getParent() {
+ return (JavaTypeMapping) super.getParent();
+ }
+
+ protected JavaTypeMapping getTypeMapping() {
+ return this.getParent();
+ }
+
+ protected JavaPersistentType getPersistentType() {
+ return this.getTypeMapping().getPersistentType();
+ }
+
+ protected JavaResourcePersistentType getResourcePersistentType() {
+ return this.getPersistentType().getResourcePersistentType();
+ }
+
+
+ // ********** PersistentType.Owner implementation **********
+
+ public AccessType getOverridePersistentTypeAccess() {
+ return this.getPersistentType().getAccess();
+ }
+
+ public AccessType getDefaultPersistentTypeAccess() {
+ // this shouldn't be needed, since we've specified an override access, but just to be safe ...
+ return this.getPersistentType().getAccess();
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ IdClassAnnotation annotation = this.getIdClassAnnotation();
+ return (annotation == null) ?
+ this.getTypeMapping().getValidationTextRange(astRoot) :
+ annotation.getTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToManyRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToManyRelationship.java
new file mode 100644
index 0000000000..acbd82eeb9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToManyRelationship.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.MappedByRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaManyToManyMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaManyToManyRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedByRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaMappingJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.resource.java.OwnableRelationshipMappingAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaManyToManyRelationship
+ extends AbstractJavaMappingRelationship<JavaManyToManyMapping>
+ implements JavaManyToManyRelationship
+{
+ protected final JavaMappedByRelationshipStrategy mappedByStrategy;
+
+ protected final JavaJoinTableRelationshipStrategy joinTableStrategy;
+
+
+ public GenericJavaManyToManyRelationship(JavaManyToManyMapping parent) {
+ super(parent);
+ this.mappedByStrategy = this.buildMappedByStrategy();
+ this.joinTableStrategy = this.buildJoinTableStrategy();
+
+ this.strategy = this.buildStrategy();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.mappedByStrategy.synchronizeWithResourceModel();
+ this.joinTableStrategy.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.mappedByStrategy.update();
+ this.joinTableStrategy.update();
+ }
+
+
+ // ********** strategy **********
+
+ @Override
+ protected JavaRelationshipStrategy buildStrategy() {
+ if (this.mappedByStrategy.getMappedByAttribute() != null) {
+ return this.mappedByStrategy;
+ }
+ return this.joinTableStrategy;
+ }
+
+
+ // ********** mapped by strategy **********
+
+ public JavaMappedByRelationshipStrategy getMappedByStrategy() {
+ return this.mappedByStrategy;
+ }
+
+ public boolean strategyIsMappedBy() {
+ return this.strategy == this.mappedByStrategy;
+ }
+
+ public void setStrategyToMappedBy() {
+ this.mappedByStrategy.addStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayBeMappedBy(AttributeMapping mapping) {
+ return mapping.getKey() == MappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ protected JavaMappedByRelationshipStrategy buildMappedByStrategy() {
+ return new GenericJavaMappedByRelationshipStrategy(this);
+ }
+
+
+ // ********** join table strategy **********
+
+ public JavaJoinTableRelationshipStrategy getJoinTableStrategy() {
+ return this.joinTableStrategy;
+ }
+
+ public boolean strategyIsJoinTable() {
+ return this.strategy == this.joinTableStrategy;
+ }
+
+ public void setStrategyToJoinTable() {
+ // join table is default option, so no need to add to resource
+ this.mappedByStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinTable() {
+ return this.getMappedByStrategy().getMappedByAttribute() == null;
+ }
+
+ protected JavaJoinTableRelationshipStrategy buildJoinTableStrategy() {
+ return new GenericJavaMappingJoinTableRelationshipStrategy(this);
+ }
+
+
+ // ********** conversions **********
+
+ public void initializeOn(Relationship newRelationship) {
+ newRelationship.initializeFromMappedByRelationship(this);
+ newRelationship.initializeFromJoinTableRelationship(this);
+ }
+
+ @Override
+ public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) {
+ super.initializeFromMappedByRelationship(oldRelationship);
+ this.mappedByStrategy.initializeFrom(oldRelationship.getMappedByStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) {
+ super.initializeFromJoinTableRelationship(oldRelationship);
+ this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy());
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaManyToManyMapping getMapping() {
+ return this.getParent();
+ }
+
+ public OwnableRelationshipMappingAnnotation getMappingAnnotation() {
+ return this.getMapping().getMappingAnnotation();
+ }
+
+ public OwnableRelationshipMappingAnnotation getMappingAnnotationForUpdate() {
+ return this.getMapping().getAnnotationForUpdate();
+ }
+
+ public boolean isOwner() {
+ return this.mappedByStrategy.getMappedByAttribute() == null;
+ }
+
+ public boolean isOwnedBy(RelationshipMapping mapping) {
+ return this.mappedByStrategy.relationshipIsOwnedBy(mapping);
+ }
+
+
+ // ********** 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.mappedByStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return this.joinTableStrategy.javaCompletionProposals(pos, filter, astRoot);
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.mappedByStrategy.validate(messages, reporter, astRoot);
+ this.joinTableStrategy.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToOneRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToOneRelationship.java
new file mode 100644
index 0000000000..c0ad6c945b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaManyToOneRelationship.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaManyToOneMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaMappingJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaManyToOneRelationship2_0;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaManyToOneRelationship
+ extends AbstractJavaMappingRelationship<JavaManyToOneMapping>
+ implements JavaManyToOneRelationship2_0
+{
+ protected final JavaJoinColumnRelationshipStrategy joinColumnStrategy;
+
+ // JPA 2.0
+ protected final JavaJoinTableRelationshipStrategy joinTableStrategy;
+
+
+ public GenericJavaManyToOneRelationship(JavaManyToOneMapping parent) {
+ super(parent);
+ this.joinColumnStrategy = this.buildJoinColumnStrategy();
+ this.joinTableStrategy = this.buildJoinTableStrategy();
+
+ this.strategy = this.buildStrategy();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.joinColumnStrategy.synchronizeWithResourceModel();
+ this.joinTableStrategy.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.joinColumnStrategy.update();
+ this.joinTableStrategy.update();
+ }
+
+
+ // ********** strategy **********
+
+ @Override
+ protected JavaRelationshipStrategy buildStrategy() {
+ if (this.isJpa2_0Compatible()) {
+ if (this.joinTableStrategy.getJoinTable() != null) {
+ return this.joinTableStrategy;
+ }
+ }
+ return this.joinColumnStrategy;
+ }
+
+
+ // ********** join table strategy **********
+
+ public JavaJoinTableRelationshipStrategy getJoinTableStrategy() {
+ return this.joinTableStrategy;
+ }
+
+ public boolean strategyIsJoinTable() {
+ return this.strategy == this.joinTableStrategy;
+ }
+
+ public final void setStrategyToJoinTable() {
+ this.joinTableStrategy.addStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinTable() {
+ return false;
+ }
+
+ protected JavaJoinTableRelationshipStrategy buildJoinTableStrategy() {
+ return this.isJpa2_0Compatible() ?
+ new GenericJavaMappingJoinTableRelationshipStrategy(this) :
+ new NullJavaJoinTableRelationshipStrategy(this);
+ }
+
+
+ // ********** join column strategy **********
+
+ public JavaJoinColumnRelationshipStrategy getJoinColumnStrategy() {
+ return this.joinColumnStrategy;
+ }
+
+ public boolean strategyIsJoinColumn() {
+ return this.strategy == this.joinColumnStrategy;
+ }
+
+ public void setStrategyToJoinColumn() {
+ // join column strategy is the default; so no need to add stuff,
+ // just remove all the others
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinColumn() {
+ return this.joinTableStrategy.getJoinTable() == null;
+ }
+
+ protected JavaJoinColumnRelationshipStrategy buildJoinColumnStrategy() {
+ return new GenericJavaMappingJoinColumnRelationshipStrategy(this);
+ }
+
+
+ // ********** conversions **********
+
+ public void initializeOn(Relationship newRelationship) {
+ newRelationship.initializeFromJoinColumnRelationship(this);
+ newRelationship.initializeFromJoinTableRelationship(this);
+ }
+
+ @Override
+ public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) {
+ super.initializeFromJoinTableRelationship(oldRelationship);
+ this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) {
+ super.initializeFromJoinColumnRelationship(oldRelationship);
+ this.joinColumnStrategy.initializeFrom(oldRelationship.getJoinColumnStrategy());
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaManyToOneMapping getMapping() {
+ return this.getParent();
+ }
+
+ public boolean isOwner() {
+ return true;
+ }
+
+ public boolean isOwnedBy(RelationshipMapping mapping) {
+ return false;
+ }
+
+
+ // ********** 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.joinColumnStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return this.joinTableStrategy.javaCompletionProposals(pos, filter, astRoot);
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.joinColumnStrategy.validate(messages, reporter, astRoot);
+ this.joinTableStrategy.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappedByRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappedByRelationshipStrategy.java
new file mode 100644
index 0000000000..f682c69d90
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappedByRelationshipStrategy.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.ArrayTools;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.Tools;
+import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.MappedByRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedByRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedByRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.resource.java.OwnableRelationshipMappingAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaMappedByRelationshipStrategy
+ extends AbstractJavaJpaContextNode
+ implements JavaMappedByRelationshipStrategy
+{
+ protected String mappedByAttribute;
+
+
+ public GenericJavaMappedByRelationshipStrategy(JavaMappedByRelationship parent) {
+ super(parent);
+ this.mappedByAttribute = this.buildMappedByAttribute();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.setMappedByAttribute_(this.buildMappedByAttribute());
+ }
+
+
+ // ********** mapped by attribute **********
+
+ public String getMappedByAttribute() {
+ return this.mappedByAttribute;
+ }
+
+ public void setMappedByAttribute(String mappedByAttribute) {
+ if (this.valuesAreDifferent(mappedByAttribute, this.mappedByAttribute)) {
+ this.getMappingAnnotationForUpdate().setMappedBy(mappedByAttribute);
+ this.setMappedByAttribute_(mappedByAttribute);
+ }
+ }
+
+ protected void setMappedByAttribute_(String mappedByAttribute) {
+ String old = this.mappedByAttribute;
+ this.mappedByAttribute = mappedByAttribute;
+ this.firePropertyChanged(MAPPED_BY_ATTRIBUTE_PROPERTY, old, mappedByAttribute);
+ }
+
+ protected String buildMappedByAttribute() {
+ OwnableRelationshipMappingAnnotation annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getMappedBy();
+ }
+
+
+ // ********** misc **********
+
+ protected OwnableRelationshipMappingAnnotation getMappingAnnotation() {
+ return this.getRelationship().getMappingAnnotation();
+ }
+
+ protected OwnableRelationshipMappingAnnotation getMappingAnnotationForUpdate() {
+ return this.getRelationship().getMappingAnnotationForUpdate();
+ }
+
+ @Override
+ public JavaMappedByRelationship getParent() {
+ return (JavaMappedByRelationship) super.getParent();
+ }
+
+ public JavaMappedByRelationship getRelationship() {
+ return this.getParent();
+ }
+
+ public void initializeFrom(MappedByRelationshipStrategy oldStrategy) {
+ this.setMappedByAttribute(oldStrategy.getMappedByAttribute());
+ }
+
+ public String getTableName() {
+ RelationshipMapping owner = this.getRelationshipOwner();
+ return (owner == null) ? null : owner.getRelationship().getStrategy().getTableName();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ RelationshipMapping owner = this.getRelationshipOwner();
+ return (owner == null) ? null : owner.getRelationship().getStrategy().resolveDbTable(tableName);
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ RelationshipMapping owner = this.getRelationshipOwner();
+ return (owner != null) && owner.getRelationship().getStrategy().tableNameIsInvalid(tableName);
+ }
+
+ public String getColumnTableNotValidDescription() {
+ //this will not be called if getRelationshipOwner() is null
+ return this.getRelationshipOwner().getRelationship().getStrategy().getColumnTableNotValidDescription();
+ }
+
+ protected RelationshipMapping getRelationshipOwner() {
+ return this.getRelationshipMapping().getRelationshipOwner();
+ }
+
+ public boolean isOverridable() {
+ return false;
+ }
+
+ protected RelationshipMapping getRelationshipMapping() {
+ return this.getRelationship().getMapping();
+ }
+
+ public boolean relationshipIsOwnedBy(RelationshipMapping otherMapping) {
+ String thisEntityName = this.getEntityName();
+ Entity otherEntity = otherMapping.getResolvedTargetEntity();
+ String otherEntityName = (otherEntity == null) ? null : otherEntity.getName();
+ return Tools.valuesAreEqual(thisEntityName, otherEntityName) &&
+ Tools.valuesAreEqual(this.mappedByAttribute, otherMapping.getName());
+ }
+
+ protected String getEntityName() {
+ Entity entity = this.getRelationship().getEntity();
+ return (entity == null) ? null : entity.getName();
+ }
+
+ public void addStrategy() {
+ if (this.mappedByAttribute == null) {
+ this.setMappedByAttribute(""); //$NON-NLS-1$
+ }
+ }
+
+ public void removeStrategy() {
+ if (this.mappedByAttribute != null) {
+ this.setMappedByAttribute(null);
+ }
+ }
+
+
+ // ********** 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;
+ }
+ OwnableRelationshipMappingAnnotation annotation = this.getMappingAnnotation();
+ if ((annotation != null) && annotation.mappedByTouches(pos, astRoot)) {
+ result = this.javaCandidateMappedByAttributeNames(filter);
+ }
+ return result;
+ }
+
+ public Iterator<String> candidateMappedByAttributeNames() {
+ return this.getRelationshipMapping().allTargetEntityAttributeNames();
+ }
+
+ protected Iterator<String> candidateMappedByAttributeNames(Filter<String> filter) {
+ return new FilteringIterator<String>(this.candidateMappedByAttributeNames(), filter);
+ }
+
+ protected Iterator<String> javaCandidateMappedByAttributeNames(Filter<String> filter) {
+ return StringTools.convertToJavaStringLiterals(this.candidateMappedByAttributeNames(filter));
+ }
+
+
+ // ********** validation **********
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ OwnableRelationshipMappingAnnotation annotation = this.getMappingAnnotation();
+ return (annotation == null) ? null : annotation.getMappedByTextRange(astRoot);
+ }
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+
+ if (this.mappedByAttribute == null) {
+ return;
+ }
+
+ Entity targetEntity = this.getRelationshipMapping().getResolvedTargetEntity();
+ if (targetEntity == null) {
+ return; // null target entity is validated elsewhere
+ }
+
+ AttributeMapping mappedByMapping = targetEntity.resolveAttributeMapping(this.mappedByAttribute);
+
+ if (mappedByMapping == null) {
+ messages.add(
+ this.buildMessage(
+ JpaValidationMessages.MAPPING_UNRESOLVED_MAPPED_BY,
+ new String[] {this.mappedByAttribute},
+ astRoot
+ )
+ );
+ return;
+ }
+
+ if ( ! this.getRelationship().mayBeMappedBy(mappedByMapping)) {
+ messages.add(
+ this.buildMessage(
+ JpaValidationMessages.MAPPING_INVALID_MAPPED_BY,
+ new String[] {this.mappedByAttribute},
+ astRoot
+ )
+ );
+ return;
+ }
+
+ // if mappedByMapping is not a relationship owner, then it should have
+ // been flagged in above rule (mappedByIsValid)
+ if ( ! ((RelationshipMapping) mappedByMapping).isRelationshipOwner()) {
+ messages.add(
+ this.buildMessage(
+ JpaValidationMessages.MAPPING_MAPPED_BY_ON_BOTH_SIDES,
+ new String[] {this.mappedByAttribute},
+ astRoot
+ )
+ );
+ }
+ }
+
+ protected IMessage buildMessage(String msgID, String[] parms, CompilationUnit astRoot) {
+ PersistentAttribute attribute = this.getRelationshipMapping().getPersistentAttribute();
+ String attributeDescription = NLS.bind(JpaValidationDescriptionMessages.ATTRIBUTE_DESC, attribute.getName());
+ parms = ArrayTools.add(parms, 0, attributeDescription);
+ return DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ msgID,
+ parms,
+ this,
+ this.getValidationTextRange(astRoot)
+ );
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappingJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappingJoinColumnRelationshipStrategy.java
new file mode 100644
index 0000000000..79b88ac1c5
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaMappingJoinColumnRelationshipStrategy.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.iterators.SubIteratorWrapper;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.JoinColumn;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappingJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.resource.java.NullJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.NestableAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+
+public class GenericJavaMappingJoinColumnRelationshipStrategy
+ extends AbstractJavaJoinColumnRelationshipStrategy
+{
+ protected final boolean targetForeignKey;
+
+
+ /**
+ * The default strategy is for a "source" foreign key.
+ */
+ public GenericJavaMappingJoinColumnRelationshipStrategy(JavaMappingJoinColumnRelationship parent) {
+ this(parent, false);
+ }
+
+ public GenericJavaMappingJoinColumnRelationshipStrategy(JavaMappingJoinColumnRelationship parent, boolean targetForeignKey) {
+ super(parent);
+ this.targetForeignKey = targetForeignKey;
+ }
+
+
+ // ********** join column annotations **********
+
+ @Override
+ protected Iterator<JoinColumnAnnotation> joinColumnAnnotations() {
+ return new SubIteratorWrapper<NestableAnnotation, JoinColumnAnnotation>(this.joinColumnAnnotations_());
+ }
+
+ protected Iterator<NestableAnnotation> joinColumnAnnotations_() {
+ return this.getResourcePersistentAttribute().annotations(JoinColumnAnnotation.ANNOTATION_NAME, JoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ @Override
+ protected JoinColumnAnnotation addJoinColumnAnnotation(int index) {
+ return (JoinColumnAnnotation) this.getResourcePersistentAttribute().addAnnotation(index, JoinColumnAnnotation.ANNOTATION_NAME, JoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ @Override
+ protected void removeJoinColumnAnnotation(int index) {
+ this.getResourcePersistentAttribute().removeAnnotation(index, JoinColumnAnnotation.ANNOTATION_NAME, JoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ @Override
+ protected void moveJoinColumnAnnotation(int targetIndex, int sourceIndex) {
+ this.getResourcePersistentAttribute().moveAnnotation(targetIndex, sourceIndex, JoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ @Override
+ protected JoinColumnAnnotation buildNullJoinColumnAnnotation() {
+ return new NullJoinColumnAnnotation(this.getResourcePersistentAttribute());
+ }
+
+
+ // ********** misc **********
+
+ protected JavaResourcePersistentAttribute getResourcePersistentAttribute() {
+ return this.getRelationship().getMapping().getResourcePersistentAttribute();
+ }
+
+ @Override
+ public JavaMappingJoinColumnRelationship getRelationship() {
+ return (JavaMappingJoinColumnRelationship) super.getRelationship();
+ }
+
+ @Override
+ protected JavaJoinColumn.Owner buildJoinColumnOwner() {
+ return new JoinColumnOwner();
+ }
+
+ public boolean isOverridable() {
+ return true;
+ }
+
+ public TypeMapping getRelationshipSource() {
+ RelationshipMapping mapping = this.getRelationshipMapping();
+ return this.targetForeignKey ?
+ mapping.getResolvedTargetEntity() :
+ mapping.getTypeMapping();
+ }
+
+ public TypeMapping getRelationshipTarget() {
+ RelationshipMapping mapping = this.getRelationshipMapping();
+ return this.targetForeignKey ?
+ mapping.getTypeMapping() :
+ mapping.getResolvedTargetEntity();
+ }
+
+ protected Entity getRelationshipTargetEntity() {
+ TypeMapping target = this.getRelationshipTarget();
+ return (target instanceof Entity) ? (Entity) target : null;
+ }
+
+ public boolean isTargetForeignKey() {
+ return this.targetForeignKey;
+ }
+
+
+ // ********** validation **********
+
+ public String getColumnTableNotValidDescription() {
+ return JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY;
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getRelationship().getValidationTextRange(astRoot);
+ }
+
+
+ // ********** join column owner **********
+
+ protected class JoinColumnOwner
+ implements JavaJoinColumn.Owner
+ {
+ protected JoinColumnOwner() {
+ super();
+ }
+
+ /**
+ * by default, the join column is in the type mapping's primary table
+ */
+ public String getDefaultTableName() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getTableName();
+ }
+
+ public String getDefaultColumnName() {
+ //built in MappingTools.buildJoinColumnDefaultName()
+ return null;
+ }
+
+ public String getAttributeName() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getRelationshipMapping().getName();
+ }
+
+ public PersistentAttribute getPersistentAttribute() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getRelationshipMapping().getPersistentAttribute();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getRelationshipSource();
+ }
+
+ public Entity getRelationshipTarget() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getRelationshipTargetEntity();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.tableNameIsInvalid(tableName);
+ }
+
+ /**
+ * the join column can be on a secondary table
+ */
+ public Iterator<String> candidateTableNames() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.candidateTableNames();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.resolveDbTable(tableName);
+ }
+
+ public Table getReferencedColumnDbTable() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getReferencedColumnDbTable();
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.defaultJoinColumn == joinColumn;
+ }
+
+ public int joinColumnsSize() {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.joinColumnsSize();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return GenericJavaMappingJoinColumnRelationshipStrategy.this.getValidationTextRange(astRoot);
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new JoinColumnValidator((JoinColumn) column, this, (JoinColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider());
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToManyRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToManyRelationship.java
new file mode 100644
index 0000000000..318babfe30
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToManyRelationship.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.MappedByRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedByRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaOneToManyMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaMappingJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOneToManyRelationship2_0;
+import org.eclipse.jpt.jpa.core.resource.java.OneToManyAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaOneToManyRelationship
+ extends AbstractJavaMappingRelationship<JavaOneToManyMapping>
+ implements JavaOneToManyRelationship2_0
+{
+ protected final JavaMappedByRelationshipStrategy mappedByStrategy;
+
+ protected final JavaJoinTableRelationshipStrategy joinTableStrategy;
+
+ // JPA 2.0 or EclipseLink
+ protected final boolean supportsJoinColumnStrategy;
+ protected final JavaJoinColumnRelationshipStrategy joinColumnStrategy;
+
+
+ public GenericJavaOneToManyRelationship(JavaOneToManyMapping parent, boolean supportsJoinColumnStrategy) {
+ super(parent);
+ this.mappedByStrategy = this.buildMappedByStrategy();
+ this.supportsJoinColumnStrategy = supportsJoinColumnStrategy;
+ this.joinColumnStrategy = this.buildJoinColumnStrategy();
+
+ // build join table strategy last since it's dependent on the other strategies
+ this.joinTableStrategy = this.buildJoinTableStrategy();
+
+ this.strategy = this.buildStrategy();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.mappedByStrategy.synchronizeWithResourceModel();
+ this.joinColumnStrategy.synchronizeWithResourceModel();
+ this.joinTableStrategy.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.mappedByStrategy.update();
+ this.joinColumnStrategy.update();
+ this.joinTableStrategy.update();
+ }
+
+
+ // ********** strategy **********
+
+ @Override
+ protected JavaRelationshipStrategy buildStrategy() {
+ if (this.mappedByStrategy.getMappedByAttribute() != null) {
+ return this.mappedByStrategy;
+ }
+ if (this.supportsJoinColumnStrategy) {
+ if (this.joinColumnStrategy.hasSpecifiedJoinColumns()) {
+ return this.joinColumnStrategy;
+ }
+ }
+ return this.joinTableStrategy;
+ }
+
+
+ // ********** mapped by strategy **********
+
+ public JavaMappedByRelationshipStrategy getMappedByStrategy() {
+ return this.mappedByStrategy;
+ }
+
+ public boolean strategyIsMappedBy() {
+ return this.strategy == this.mappedByStrategy;
+ }
+
+ public final void setStrategyToMappedBy() {
+ this.mappedByStrategy.addStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayBeMappedBy(AttributeMapping mapping) {
+ String key = mapping.getKey();
+ if (key == MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
+ return true;
+ }
+ if (this.supportsJoinColumnStrategy) {
+ return key == MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+ return false;
+ }
+
+ protected JavaMappedByRelationshipStrategy buildMappedByStrategy() {
+ return new GenericJavaMappedByRelationshipStrategy(this);
+ }
+
+
+ // ********** join table strategy **********
+
+ public JavaJoinTableRelationshipStrategy getJoinTableStrategy() {
+ return this.joinTableStrategy;
+ }
+
+ public boolean strategyIsJoinTable() {
+ return this.strategy == this.joinTableStrategy;
+ }
+
+ public final void setStrategyToJoinTable() {
+ // join table is default, so no need to add annotation
+ this.mappedByStrategy.removeStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinTable() {
+ return (this.mappedByStrategy.getMappedByAttribute() == null) &&
+ ! this.joinColumnStrategy.hasSpecifiedJoinColumns();
+ }
+
+ protected JavaJoinTableRelationshipStrategy buildJoinTableStrategy() {
+ return new GenericJavaMappingJoinTableRelationshipStrategy(this);
+ }
+
+
+ // ********** join column strategy **********
+
+ public JavaJoinColumnRelationshipStrategy getJoinColumnStrategy() {
+ return this.joinColumnStrategy;
+ }
+
+ public boolean strategyIsJoinColumn() {
+ return this.strategy == this.joinColumnStrategy;
+ }
+
+ public void setStrategyToJoinColumn() {
+ this.joinColumnStrategy.addStrategy();
+ this.mappedByStrategy.removeStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinColumn() {
+ return false;
+ }
+
+ protected JavaJoinColumnRelationshipStrategy buildJoinColumnStrategy() {
+ return this.supportsJoinColumnStrategy ?
+ new GenericJavaMappingJoinColumnRelationshipStrategy(this, true) : // true = target foreign key
+ new NullJavaJoinColumnRelationshipStrategy(this);
+ }
+
+
+ // ********** conversions **********
+
+ public void initializeOn(Relationship newRelationship) {
+ newRelationship.initializeFromMappedByRelationship(this);
+ newRelationship.initializeFromJoinTableRelationship(this);
+ newRelationship.initializeFromJoinColumnRelationship(this);
+ }
+
+ @Override
+ public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) {
+ super.initializeFromMappedByRelationship(oldRelationship);
+ this.mappedByStrategy.initializeFrom(oldRelationship.getMappedByStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) {
+ super.initializeFromJoinTableRelationship(oldRelationship);
+ this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) {
+ super.initializeFromJoinColumnRelationship(oldRelationship);
+ this.joinColumnStrategy.initializeFrom(oldRelationship.getJoinColumnStrategy());
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaOneToManyMapping getMapping() {
+ return this.getParent();
+ }
+
+ public OneToManyAnnotation getMappingAnnotation() {
+ return this.getMapping().getMappingAnnotation();
+ }
+
+ public OneToManyAnnotation getMappingAnnotationForUpdate() {
+ return this.getMapping().getAnnotationForUpdate();
+ }
+
+ public boolean isOwner() {
+ return this.mappedByStrategy.getMappedByAttribute() == null;
+ }
+
+ public boolean isOwnedBy(RelationshipMapping mapping) {
+ return this.mappedByStrategy.relationshipIsOwnedBy(mapping);
+ }
+
+ @Override
+ public boolean isTargetForeignKey() {
+ return this.joinColumnStrategy.isTargetForeignKey();
+ }
+
+
+ // ********** 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.mappedByStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ result = this.joinTableStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return this.joinColumnStrategy.javaCompletionProposals(pos, filter, astRoot);
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.mappedByStrategy.validate(messages, reporter, astRoot);
+ this.joinTableStrategy.validate(messages, reporter, astRoot);
+ this.joinColumnStrategy.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToOneRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToOneRelationship.java
new file mode 100644
index 0000000000..8ea6e4ef66
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOneToOneRelationship.java
@@ -0,0 +1,300 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.MappedByRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship;
+import org.eclipse.jpt.jpa.core.context.Relationship;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedByRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaOneToOneMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaMappingJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOneToOneRelationship2_0;
+import org.eclipse.jpt.jpa.core.resource.java.OwnableRelationshipMappingAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaOneToOneRelationship
+ extends AbstractJavaMappingRelationship<JavaOneToOneMapping>
+ implements JavaOneToOneRelationship2_0
+{
+ protected final JavaMappedByRelationshipStrategy mappedByStrategy;
+
+ protected final JavaPrimaryKeyJoinColumnRelationshipStrategy primaryKeyJoinColumnStrategy;
+
+ // JPA 2.0
+ protected final JavaJoinTableRelationshipStrategy joinTableStrategy;
+
+ protected final JavaJoinColumnRelationshipStrategy joinColumnStrategy;
+
+
+ public GenericJavaOneToOneRelationship(JavaOneToOneMapping parent) {
+ super(parent);
+ this.mappedByStrategy = this.buildMappedByStrategy();
+ this.primaryKeyJoinColumnStrategy = this.buildPrimaryKeyJoinColumnStrategy();
+ this.joinTableStrategy = this.buildJoinTableStrategy();
+ this.joinColumnStrategy = this.buildJoinColumnStrategy();
+
+ this.strategy = this.buildStrategy();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.mappedByStrategy.synchronizeWithResourceModel();
+ this.primaryKeyJoinColumnStrategy.synchronizeWithResourceModel();
+ this.joinTableStrategy.synchronizeWithResourceModel();
+ this.joinColumnStrategy.synchronizeWithResourceModel();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.mappedByStrategy.update();
+ this.primaryKeyJoinColumnStrategy.update();
+ this.joinTableStrategy.update();
+ this.joinColumnStrategy.update();
+ }
+
+
+ // ********** strategy **********
+
+ @Override
+ protected JavaRelationshipStrategy buildStrategy() {
+ if (this.mappedByStrategy.getMappedByAttribute() != null) {
+ return this.mappedByStrategy;
+ }
+ if (this.primaryKeyJoinColumnStrategy.hasPrimaryKeyJoinColumns()) {
+ return this.primaryKeyJoinColumnStrategy;
+ }
+ if (this.isJpa2_0Compatible()) {
+ if (this.joinTableStrategy.getJoinTable() != null) {
+ return this.joinTableStrategy;
+ }
+ }
+ return this.joinColumnStrategy;
+ }
+
+
+ // ********** mapped by strategy **********
+
+ public JavaMappedByRelationshipStrategy getMappedByStrategy() {
+ return this.mappedByStrategy;
+ }
+
+ public boolean strategyIsMappedBy() {
+ return this.strategy == this.mappedByStrategy;
+ }
+
+ public void setStrategyToMappedBy() {
+ this.mappedByStrategy.addStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.primaryKeyJoinColumnStrategy.removeStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayBeMappedBy(AttributeMapping mapping) {
+ return mapping.getKey() == MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ protected JavaMappedByRelationshipStrategy buildMappedByStrategy() {
+ return new GenericJavaMappedByRelationshipStrategy(this);
+ }
+
+
+ // ********** primary key join column strategy **********
+
+ public JavaPrimaryKeyJoinColumnRelationshipStrategy getPrimaryKeyJoinColumnStrategy() {
+ return this.primaryKeyJoinColumnStrategy;
+ }
+
+ public boolean strategyIsPrimaryKeyJoinColumn() {
+ return this.strategy == this.primaryKeyJoinColumnStrategy;
+ }
+
+ public void setStrategyToPrimaryKeyJoinColumn() {
+ this.primaryKeyJoinColumnStrategy.addStrategy();
+ this.mappedByStrategy.removeStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ protected JavaPrimaryKeyJoinColumnRelationshipStrategy buildPrimaryKeyJoinColumnStrategy() {
+ return new GenericJavaPrimaryKeyJoinColumnRelationshipStrategy(this);
+ }
+
+
+ // ********** join table strategy **********
+
+ public JavaJoinTableRelationshipStrategy getJoinTableStrategy() {
+ return this.joinTableStrategy;
+ }
+
+ public boolean strategyIsJoinTable() {
+ return this.strategy == this.joinTableStrategy;
+ }
+
+ public final void setStrategyToJoinTable() {
+ this.joinTableStrategy.addStrategy();
+ this.mappedByStrategy.removeStrategy();
+ this.joinColumnStrategy.removeStrategy();
+ this.primaryKeyJoinColumnStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinTable() {
+ return false;
+ }
+
+ protected JavaJoinTableRelationshipStrategy buildJoinTableStrategy() {
+ return this.isJpa2_0Compatible() ?
+ new GenericJavaMappingJoinTableRelationshipStrategy(this) :
+ new NullJavaJoinTableRelationshipStrategy(this);
+ }
+
+
+ // ********** join column strategy **********
+
+ public JavaJoinColumnRelationshipStrategy getJoinColumnStrategy() {
+ return this.joinColumnStrategy;
+ }
+
+ public boolean strategyIsJoinColumn() {
+ return this.strategy == this.joinColumnStrategy;
+ }
+
+ public void setStrategyToJoinColumn() {
+ // join column strategy is the default; so no need to add stuff,
+ // just remove all the others
+ this.mappedByStrategy.removeStrategy();
+ this.primaryKeyJoinColumnStrategy.removeStrategy();
+ this.joinTableStrategy.removeStrategy();
+ this.updateStrategy();
+ }
+
+ public boolean mayHaveDefaultJoinColumn() {
+ return (this.mappedByStrategy.getMappedByAttribute() == null) &&
+ (this.primaryKeyJoinColumnStrategy.primaryKeyJoinColumnsSize() == 0) &&
+ (this.joinTableStrategy.getJoinTable() == null);
+ }
+
+ protected JavaJoinColumnRelationshipStrategy buildJoinColumnStrategy() {
+ return new GenericJavaMappingJoinColumnRelationshipStrategy(this);
+ }
+
+
+ // ********** conversions **********
+
+ public void initializeOn(Relationship newRelationship) {
+ newRelationship.initializeFromMappedByRelationship(this);
+ newRelationship.initializeFromJoinTableRelationship(this);
+ newRelationship.initializeFromJoinColumnRelationship(this);
+ // no other pk join column relationships yet
+ }
+
+ @Override
+ public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) {
+ super.initializeFromMappedByRelationship(oldRelationship);
+ this.mappedByStrategy.initializeFrom(oldRelationship.getMappedByStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) {
+ super.initializeFromJoinTableRelationship(oldRelationship);
+ this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy());
+ }
+
+ @Override
+ public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) {
+ super.initializeFromJoinColumnRelationship(oldRelationship);
+ this.joinColumnStrategy.initializeFrom(oldRelationship.getJoinColumnStrategy());
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaOneToOneMapping getMapping() {
+ return this.getParent();
+ }
+
+ public OwnableRelationshipMappingAnnotation getMappingAnnotation() {
+ return this.getMapping().getMappingAnnotation();
+ }
+
+ public OwnableRelationshipMappingAnnotation getMappingAnnotationForUpdate() {
+ return this.getMapping().getAnnotationForUpdate();
+ }
+
+ public boolean isOwner() {
+ return this.mappedByStrategy.getMappedByAttribute() == null;
+ }
+
+ public boolean isOwnedBy(RelationshipMapping mapping) {
+ return this.mappedByStrategy.relationshipIsOwnedBy(mapping);
+ }
+
+
+ // ********** 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.mappedByStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ result = this.primaryKeyJoinColumnStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ result = this.joinTableStrategy.javaCompletionProposals(pos, filter, astRoot);
+ if (result != null) {
+ return result;
+ }
+
+ return this.joinColumnStrategy.javaCompletionProposals(pos, filter, astRoot);
+ }
+
+
+ // ********** validation **********
+
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ this.mappedByStrategy.validate(messages, reporter, astRoot);
+ this.primaryKeyJoinColumnStrategy.validate(messages, reporter, astRoot);
+ this.joinColumnStrategy.validate(messages, reporter, astRoot);
+ this.joinTableStrategy.validate(messages, reporter, astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOverrideJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOverrideJoinColumnRelationshipStrategy.java
new file mode 100644
index 0000000000..9190e16939
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaOverrideJoinColumnRelationshipStrategy.java
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.context.java;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.BaseColumn;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAssociationOverride;
+import org.eclipse.jpt.jpa.core.context.java.JavaAssociationOverrideContainer;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverrideRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn.Owner;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.resource.java.NullJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AssociationOverrideAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+
+public class GenericJavaOverrideJoinColumnRelationshipStrategy
+ extends AbstractJavaJoinColumnRelationshipStrategy
+{
+ public GenericJavaOverrideJoinColumnRelationshipStrategy(JavaOverrideRelationship parent) {
+ super(parent);
+ }
+
+
+ // ********** join column annotations **********
+
+ @Override
+ protected ListIterator<JoinColumnAnnotation> joinColumnAnnotations() {
+ return this.getOverrideAnnotation().joinColumns();
+ }
+
+ @Override
+ protected JoinColumnAnnotation addJoinColumnAnnotation(int index) {
+ return this.getOverrideAnnotation().addJoinColumn(index);
+ }
+
+ @Override
+ protected void removeJoinColumnAnnotation(int index) {
+ this.getOverrideAnnotation().removeJoinColumn(index);
+ }
+
+ @Override
+ protected void moveJoinColumnAnnotation(int targetIndex, int sourceIndex) {
+ this.getOverrideAnnotation().moveJoinColumn(targetIndex, sourceIndex);
+ }
+
+ @Override
+ protected JoinColumnAnnotation buildNullJoinColumnAnnotation() {
+ return new NullJoinColumnAnnotation(this.getOverrideAnnotation());
+ }
+
+ protected AssociationOverrideAnnotation getOverrideAnnotation() {
+ return this.getAssociationOverride().getOverrideAnnotation();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ protected Owner buildJoinColumnOwner() {
+ return new JoinColumnOwner();
+ }
+
+ public boolean isTargetForeignKey() {
+ RelationshipMapping relationshipMapping = this.getRelationshipMapping();
+ return (relationshipMapping != null) &&
+ relationshipMapping.getRelationship().isTargetForeignKey();
+ }
+
+ public TypeMapping getRelationshipSource() {
+ return this.isTargetForeignKey() ?
+ this.getRelationshipMapping().getResolvedTargetEntity() :
+ this.getAssociationOverrideContainer().getTypeMapping();
+ }
+
+ public TypeMapping getRelationshipTarget() {
+ return this.isTargetForeignKey() ?
+ this.getAssociationOverrideContainer().getTypeMapping() :
+ this.getRelationshipMappingTargetEntity();
+ }
+
+ protected TypeMapping getRelationshipMappingTargetEntity() {
+ RelationshipMapping mapping = this.getRelationshipMapping();
+ return (mapping == null) ? null : mapping.getResolvedTargetEntity();
+ }
+
+ protected Entity getRelationshipTargetEntity() {
+ TypeMapping target = this.getRelationshipTarget();
+ return (target instanceof Entity) ? (Entity) target : null;
+ }
+
+ @Override
+ public RelationshipMapping getRelationshipMapping() {
+ return this.getAssociationOverride().getMapping();
+ }
+
+ protected String getAttributeName() {
+ return this.getAssociationOverride().getName();
+ }
+
+ @Override
+ public String getTableName() {
+ return this.isTargetForeignKey() ?
+ super.getTableName() :
+ this.getAssociationOverrideContainer().getDefaultTableName();
+ }
+
+ @Override
+ public Table resolveDbTable(String tableName) {
+ return this.isTargetForeignKey() ?
+ super.resolveDbTable(tableName) :
+ this.getAssociationOverrideContainer().resolveDbTable(tableName);
+ }
+
+ @Override
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.isTargetForeignKey() ?
+ super.tableNameIsInvalid(tableName) :
+ this.getAssociationOverrideContainer().tableNameIsInvalid(tableName);
+ }
+
+ @Override
+ public Iterator<String> candidateTableNames() {
+ return this.isTargetForeignKey() ?
+ super.candidateTableNames() :
+ this.getAssociationOverrideContainer().candidateTableNames();
+ }
+
+ public String getColumnTableNotValidDescription() {
+ return null;
+ }
+
+ public boolean isOverridable() {
+ return false;
+ }
+
+ protected JavaAssociationOverride getAssociationOverride() {
+ return this.getRelationship().getAssociationOverride();
+ }
+
+ protected JavaAssociationOverrideContainer getAssociationOverrideContainer() {
+ return this.getAssociationOverride().getContainer();
+ }
+
+ @Override
+ public JavaOverrideRelationship getRelationship() {
+ return (JavaOverrideRelationship) super.getRelationship();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getRelationship().getValidationTextRange(astRoot);
+ }
+
+
+ // ********** join column owner adapter **********
+
+ protected class JoinColumnOwner
+ implements JavaJoinColumn.Owner
+ {
+ protected JoinColumnOwner() {
+ super();
+ }
+
+ public String getDefaultTableName() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getTableName();
+ }
+
+ public String getDefaultColumnName() {
+ //built in MappingTools.buildJoinColumnDefaultName()
+ return null;
+ }
+
+ public String getAttributeName() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getAttributeName();
+ }
+
+ public PersistentAttribute getPersistentAttribute() {
+ RelationshipMapping relationshipMapping = GenericJavaOverrideJoinColumnRelationshipStrategy.this.getRelationshipMapping();
+ return relationshipMapping == null ? null : relationshipMapping.getPersistentAttribute();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getRelationshipSource();
+ }
+
+ public Entity getRelationshipTarget() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getRelationshipTargetEntity();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.tableNameIsInvalid(tableName);
+ }
+
+ public Iterator<String> candidateTableNames() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.candidateTableNames();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.resolveDbTable(tableName);
+ }
+
+ public Table getReferencedColumnDbTable() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getReferencedColumnDbTable();
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return false;
+ }
+
+ public int joinColumnsSize() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.joinColumnsSize();
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getValidationTextRange(astRoot);
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return this.getAssociationOverrideContainer().buildColumnValidator(this.getAssociationOverride(), (BaseColumn) column, this, (BaseColumnTextRangeResolver) textRangeResolver);
+ }
+
+ protected JavaAssociationOverride getAssociationOverride() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getAssociationOverride();
+ }
+
+ protected JavaAssociationOverrideContainer getAssociationOverrideContainer() {
+ return GenericJavaOverrideJoinColumnRelationshipStrategy.this.getAssociationOverrideContainer();
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.java
new file mode 100644
index 0000000000..188364f29b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 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.jpa.core.internal.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.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.Filter;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterators.SubIteratorWrapper;
+import org.eclipse.jpt.jpa.core.context.BaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.NamedColumn;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.PrimaryKeyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumnRelationship;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumnRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaRelationshipMapping;
+import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+import org.eclipse.jpt.jpa.core.internal.jpa1.context.OneToOnePrimaryKeyJoinColumnValidator;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.NestableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.db.Table;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+public class GenericJavaPrimaryKeyJoinColumnRelationshipStrategy
+ extends AbstractJavaJpaContextNode
+ implements JavaPrimaryKeyJoinColumnRelationshipStrategy
+{
+ protected final Vector<JavaPrimaryKeyJoinColumn> primaryKeyJoinColumns = new Vector<JavaPrimaryKeyJoinColumn>();
+ protected final PrimaryKeyJoinColumnContainerAdapter primaryKeyJoinColumnContainerAdapter;
+ protected final JavaJoinColumn.Owner primaryKeyJoinColumnOwner;
+
+
+ public GenericJavaPrimaryKeyJoinColumnRelationshipStrategy(JavaPrimaryKeyJoinColumnRelationship parent) {
+ super(parent);
+ this.primaryKeyJoinColumnContainerAdapter = this.buildPrimaryKeyJoinColumnContainerAdapter();
+ this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner();
+ this.initializePrimaryKeyJoinColumns();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void synchronizeWithResourceModel() {
+ super.synchronizeWithResourceModel();
+ this.syncPrimaryKeyJoinColumns();
+ }
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateNodes(this.getPrimaryKeyJoinColumns());
+ }
+
+
+ // ********** primary key join columns **********
+
+ public ListIterator<JavaPrimaryKeyJoinColumn> primaryKeyJoinColumns() {
+ return this.getPrimaryKeyJoinColumns().iterator();
+ }
+
+ public ListIterable<JavaPrimaryKeyJoinColumn> getPrimaryKeyJoinColumns() {
+ return new LiveCloneListIterable<JavaPrimaryKeyJoinColumn>(this.primaryKeyJoinColumns);
+ }
+
+ public int primaryKeyJoinColumnsSize() {
+ return this.primaryKeyJoinColumns.size();
+ }
+
+ public boolean hasPrimaryKeyJoinColumns() {
+ return this.primaryKeyJoinColumns.size() != 0;
+ }
+
+ public JavaPrimaryKeyJoinColumn getPrimaryKeyJoinColumn(int index) {
+ return this.primaryKeyJoinColumns.get(index);
+ }
+
+ public JavaPrimaryKeyJoinColumn addPrimaryKeyJoinColumn() {
+ return this.addPrimaryKeyJoinColumn(this.primaryKeyJoinColumns.size());
+ }
+
+ public JavaPrimaryKeyJoinColumn addPrimaryKeyJoinColumn(int index) {
+ PrimaryKeyJoinColumnAnnotation annotation = this.addPrimaryKeyJoinColumnAnnotation(index);
+ return this.addPrimaryKeyJoinColumn_(index, annotation);
+ }
+
+ public void removePrimaryKeyJoinColumn(PrimaryKeyJoinColumn joinColumn) {
+ this.removePrimaryKeyJoinColumn(this.primaryKeyJoinColumns.indexOf(joinColumn));
+ }
+
+ public void removePrimaryKeyJoinColumn(int index) {
+ this.removePrimaryKeyJoinColumnAnnotation(index);
+ this.removePrimaryKeyJoinColumn_(index);
+ }
+
+ protected void removePrimaryKeyJoinColumn_(int index) {
+ this.removeItemFromList(index, this.primaryKeyJoinColumns, PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ public void movePrimaryKeyJoinColumn(int targetIndex, int sourceIndex) {
+ this.movePrimaryKeyJoinColumnAnnotation(targetIndex, sourceIndex);
+ this.moveItemInList(targetIndex, sourceIndex, this.primaryKeyJoinColumns, PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ protected void initializePrimaryKeyJoinColumns() {
+ for (PrimaryKeyJoinColumnAnnotation annotation : this.getPrimaryKeyJoinColumnAnnotations()) {
+ this.primaryKeyJoinColumns.add(this.buildPrimaryKeyJoinColumn(annotation));
+ }
+ }
+
+ protected void syncPrimaryKeyJoinColumns() {
+ ContextContainerTools.synchronizeWithResourceModel(this.primaryKeyJoinColumnContainerAdapter);
+ }
+
+ protected Iterable<PrimaryKeyJoinColumnAnnotation> getPrimaryKeyJoinColumnAnnotations() {
+ return CollectionTools.iterable(this.primaryKeyJoinColumnAnnotations());
+ }
+
+ protected void movePrimaryKeyJoinColumn_(int index, JavaPrimaryKeyJoinColumn joinColumn) {
+ this.moveItemInList(index, joinColumn, this.primaryKeyJoinColumns, PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ }
+
+ protected JavaPrimaryKeyJoinColumn addPrimaryKeyJoinColumn_(int index, PrimaryKeyJoinColumnAnnotation pkJoinColumnAnnotation) {
+ JavaPrimaryKeyJoinColumn joinColumn = this.buildPrimaryKeyJoinColumn(pkJoinColumnAnnotation);
+ this.addItemToList(index, joinColumn, this.primaryKeyJoinColumns, PRIMARY_KEY_JOIN_COLUMNS_LIST);
+ return joinColumn;
+ }
+
+ protected void removePrimaryKeyJoinColumn_(JavaPrimaryKeyJoinColumn joinColumn) {
+ this.removePrimaryKeyJoinColumn_(this.primaryKeyJoinColumns.indexOf(joinColumn));
+ }
+
+ protected PrimaryKeyJoinColumnContainerAdapter buildPrimaryKeyJoinColumnContainerAdapter() {
+ return new PrimaryKeyJoinColumnContainerAdapter();
+ }
+
+ /**
+ * primary key join column container adapter
+ */
+ protected class PrimaryKeyJoinColumnContainerAdapter
+ implements ContextContainerTools.Adapter<JavaPrimaryKeyJoinColumn, PrimaryKeyJoinColumnAnnotation>
+ {
+ public Iterable<JavaPrimaryKeyJoinColumn> getContextElements() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getPrimaryKeyJoinColumns();
+ }
+ public Iterable<PrimaryKeyJoinColumnAnnotation> getResourceElements() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getPrimaryKeyJoinColumnAnnotations();
+ }
+ public PrimaryKeyJoinColumnAnnotation getResourceElement(JavaPrimaryKeyJoinColumn contextElement) {
+ return contextElement.getColumnAnnotation();
+ }
+ public void moveContextElement(int index, JavaPrimaryKeyJoinColumn element) {
+ GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.movePrimaryKeyJoinColumn_(index, element);
+ }
+ public void addContextElement(int index, PrimaryKeyJoinColumnAnnotation resourceElement) {
+ GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.addPrimaryKeyJoinColumn_(index, resourceElement);
+ }
+ public void removeContextElement(JavaPrimaryKeyJoinColumn element) {
+ GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.removePrimaryKeyJoinColumn_(element);
+ }
+ }
+
+ protected JavaJoinColumn.Owner buildPrimaryKeyJoinColumnOwner() {
+ return new PrimaryKeyJoinColumnOwner();
+ }
+
+ protected JavaPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(PrimaryKeyJoinColumnAnnotation annotation) {
+ return this.getJpaFactory().buildJavaPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner, annotation);
+ }
+
+
+ // ********** primary key join column annotations **********
+
+ protected Iterator<PrimaryKeyJoinColumnAnnotation> primaryKeyJoinColumnAnnotations() {
+ return new SubIteratorWrapper<NestableAnnotation, PrimaryKeyJoinColumnAnnotation>(this.primaryKeyJoinColumnAnnotations_());
+ }
+
+ protected Iterator<NestableAnnotation> primaryKeyJoinColumnAnnotations_() {
+ return this.getResourcePersistentAttribute().annotations(PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ protected PrimaryKeyJoinColumnAnnotation addPrimaryKeyJoinColumnAnnotation(int index) {
+ return (PrimaryKeyJoinColumnAnnotation) this.getResourcePersistentAttribute().addAnnotation(index, PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void removePrimaryKeyJoinColumnAnnotation(int index) {
+ this.getResourcePersistentAttribute().removeAnnotation(index, PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+ protected void movePrimaryKeyJoinColumnAnnotation(int targetIndex, int sourceIndex) {
+ this.getResourcePersistentAttribute().moveAnnotation(targetIndex, sourceIndex, PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME);
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaPrimaryKeyJoinColumnRelationship getParent() {
+ return (JavaPrimaryKeyJoinColumnRelationship) super.getParent();
+ }
+
+ public JavaPrimaryKeyJoinColumnRelationship getRelationship() {
+ return this.getParent();
+ }
+
+ protected JavaRelationshipMapping getRelationshipMapping() {
+ return this.getRelationship().getMapping();
+ }
+
+ protected JavaResourcePersistentAttribute getResourcePersistentAttribute() {
+ return this.getRelationship().getMapping().getResourcePersistentAttribute();
+ }
+
+ public String getTableName() {
+ return this.getTypeMapping().getPrimaryTableName();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return this.getTypeMapping().resolveDbTable(tableName);
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ public boolean isOverridable() {
+ return false;
+ }
+
+ public String getColumnTableNotValidDescription() {
+ return JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY;
+ }
+
+ protected TypeMapping getTypeMapping() {
+ return this.getRelationshipMapping().getTypeMapping();
+ }
+
+ public void addStrategy() {
+ if (this.primaryKeyJoinColumns.size() == 0) {
+ this.addPrimaryKeyJoinColumn();
+ }
+ }
+
+ public void removeStrategy() {
+ for (int i = this.primaryKeyJoinColumns.size(); i-- > 0; ) {
+ this.removePrimaryKeyJoinColumn(i);
+ }
+ }
+
+
+ // ********** 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 (JavaPrimaryKeyJoinColumn column : this.getPrimaryKeyJoinColumns()) {
+ result = column.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 (JavaPrimaryKeyJoinColumn pkJoinColumn : this.getPrimaryKeyJoinColumns()) {
+ pkJoinColumn.validate(messages, reporter, astRoot);
+ }
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getRelationship().getValidationTextRange(astRoot);
+ }
+
+
+ // ********** join column owner **********
+
+ protected class PrimaryKeyJoinColumnOwner
+ implements JavaJoinColumn.Owner
+ {
+ protected PrimaryKeyJoinColumnOwner() {
+ super();
+ }
+
+ /**
+ * by default, the join column is in the type mapping's primary table
+ */
+ public String getDefaultTableName() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getTableName();
+ }
+
+ public Entity getRelationshipTarget() {
+ return this.getRelationshipMapping().getResolvedTargetEntity();
+ }
+
+ public String getAttributeName() {
+ return this.getRelationshipMapping().getName();
+ }
+
+ public PersistentAttribute getPersistentAttribute() {
+ return this.getRelationshipMapping().getPersistentAttribute();
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return this.getTypeMapping().tableNameIsInvalid(tableName);
+ }
+
+ /**
+ * the join column can be on a secondary table
+ */
+ public Iterator<String> candidateTableNames() {
+ return this.getTypeMapping().allAssociatedTableNames();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getTypeMapping();
+ }
+
+ public Table resolveDbTable(String tableName) {
+ return this.getTypeMapping().resolveDbTable(tableName);
+ }
+
+ public Table getReferencedColumnDbTable() {
+ Entity targetEntity = this.getRelationshipTarget();
+ return (targetEntity == null) ? null : targetEntity.getPrimaryDbTable();
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return false;
+ }
+
+ public String getDefaultColumnName() {
+ return null;
+ }
+
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getValidationTextRange(astRoot);
+ }
+
+ public int joinColumnsSize() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.primaryKeyJoinColumnsSize();
+ }
+
+ public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) {
+ return new OneToOnePrimaryKeyJoinColumnValidator((BaseJoinColumn) column, this, (BaseJoinColumnTextRangeResolver) textRangeResolver);
+ }
+
+ protected JavaRelationshipMapping getRelationshipMapping() {
+ return GenericJavaPrimaryKeyJoinColumnRelationshipStrategy.this.getRelationshipMapping();
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaVirtualJoinTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaVirtualJoinTable.java
new file mode 100644
index 0000000000..f27ca4df39
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/GenericJavaVirtualJoinTable.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.jpa.core.internal.context.java;
+
+import java.util.ListIterator;
+import java.util.Vector;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
+import org.eclipse.jpt.common.utility.internal.iterables.SingleElementListIterable;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.JoinColumn;
+import org.eclipse.jpt.jpa.core.context.JoinTable;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn;
+import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn;
+import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumn;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinTable;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinTableRelationshipStrategy;
+import org.eclipse.jpt.jpa.core.context.java.JavaVirtualRelationship;
+import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools;
+import org.eclipse.jpt.jpa.core.internal.context.MappingTools;
+
+/**
+ * Java virtual join table
+ */
+public class GenericJavaVirtualJoinTable
+ extends AbstractJavaVirtualReferenceTable<JoinTable>
+ implements JavaVirtualJoinTable
+{
+ protected final JoinTable overriddenTable;
+
+ protected final Vector<JavaVirtualJoinColumn> specifiedInverseJoinColumns = new Vector<JavaVirtualJoinColumn>();
+ protected final SpecifiedInverseJoinColumnContainerAdapter specifiedInverseJoinColumnContainerAdapter = new SpecifiedInverseJoinColumnContainerAdapter();
+ protected final ReadOnlyJoinColumn.Owner inverseJoinColumnOwner;
+
+ protected JavaVirtualJoinColumn defaultInverseJoinColumn;
+
+
+ public GenericJavaVirtualJoinTable(JavaVirtualJoinTableRelationshipStrategy parent, JoinTable overriddenTable) {
+ super(parent);
+ this.overriddenTable = overriddenTable;
+ this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner();
+ }
+
+
+ // ********** synchronize/update **********
+
+ @Override
+ public void update() {
+ super.update();
+ this.updateSpecifiedInverseJoinColumns();
+ this.updateDefaultInverseJoinColumn();
+ }
+
+
+ // ********** table **********
+
+ @Override
+ public JoinTable getOverriddenTable() {
+ return this.overriddenTable;
+ }
+
+
+ // ********** inverse join columns **********
+
+ public ListIterator<JavaVirtualJoinColumn> inverseJoinColumns() {
+ return this.getInverseJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getInverseJoinColumns() {
+ return this.hasSpecifiedInverseJoinColumns() ? this.getSpecifiedInverseJoinColumns() : this.getDefaultInverseJoinColumns();
+ }
+
+ public int inverseJoinColumnsSize() {
+ return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumnsSize() : this.getDefaultInverseJoinColumnsSize();
+ }
+
+
+ // ********** inverse specified join columns **********
+
+ public ListIterator<JavaVirtualJoinColumn> specifiedInverseJoinColumns() {
+ return this.getSpecifiedInverseJoinColumns().iterator();
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getSpecifiedInverseJoinColumns() {
+ return new LiveCloneListIterable<JavaVirtualJoinColumn>(this.specifiedInverseJoinColumns);
+ }
+
+ public int specifiedInverseJoinColumnsSize() {
+ return this.specifiedInverseJoinColumns.size();
+ }
+
+ public boolean hasSpecifiedInverseJoinColumns() {
+ return this.specifiedInverseJoinColumns.size() != 0;
+ }
+
+ public JavaVirtualJoinColumn getSpecifiedInverseJoinColumn(int index) {
+ return this.specifiedInverseJoinColumns.get(index);
+ }
+
+ protected void updateSpecifiedInverseJoinColumns() {
+ ContextContainerTools.update(this.specifiedInverseJoinColumnContainerAdapter);
+ }
+
+ protected Iterable<JoinColumn> getOverriddenInverseJoinColumns() {
+ return CollectionTools.iterable(this.getOverriddenTable().specifiedInverseJoinColumns());
+ }
+
+ protected void moveSpecifiedInverseJoinColumn(int index, JavaVirtualJoinColumn joinColumn) {
+ this.moveItemInList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST);
+ }
+
+ protected JavaVirtualJoinColumn addSpecifiedInverseJoinColumn(int index, JoinColumn joinColumn) {
+ JavaVirtualJoinColumn virtualJoinColumn = this.buildInverseJoinColumn(joinColumn);
+ this.addItemToList(index, virtualJoinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST);
+ return virtualJoinColumn;
+ }
+
+ protected void removeSpecifiedInverseJoinColumn(JavaVirtualJoinColumn joinColumn) {
+ this.removeItemFromList(joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST);
+ }
+
+ /**
+ * specified inverse join column container adapter
+ */
+ protected class SpecifiedInverseJoinColumnContainerAdapter
+ implements ContextContainerTools.Adapter<JavaVirtualJoinColumn, JoinColumn>
+ {
+ public Iterable<JavaVirtualJoinColumn> getContextElements() {
+ return GenericJavaVirtualJoinTable.this.getSpecifiedInverseJoinColumns();
+ }
+ public Iterable<JoinColumn> getResourceElements() {
+ return GenericJavaVirtualJoinTable.this.getOverriddenInverseJoinColumns();
+ }
+ public JoinColumn getResourceElement(JavaVirtualJoinColumn contextElement) {
+ return contextElement.getOverriddenColumn();
+ }
+ public void moveContextElement(int index, JavaVirtualJoinColumn element) {
+ GenericJavaVirtualJoinTable.this.moveSpecifiedInverseJoinColumn(index, element);
+ }
+ public void addContextElement(int index, JoinColumn element) {
+ GenericJavaVirtualJoinTable.this.addSpecifiedInverseJoinColumn(index, element);
+ }
+ public void removeContextElement(JavaVirtualJoinColumn element) {
+ GenericJavaVirtualJoinTable.this.removeSpecifiedInverseJoinColumn(element);
+ }
+ }
+
+
+ // ********** default inverse join column **********
+
+ public JavaVirtualJoinColumn getDefaultInverseJoinColumn() {
+ return this.defaultInverseJoinColumn;
+ }
+
+ protected void setDefaultInverseJoinColumn(JavaVirtualJoinColumn joinColumn) {
+ JavaVirtualJoinColumn old = this.defaultInverseJoinColumn;
+ this.defaultInverseJoinColumn = joinColumn;
+ this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, old, joinColumn);
+ }
+
+ protected ListIterable<JavaVirtualJoinColumn> getDefaultInverseJoinColumns() {
+ return (this.defaultInverseJoinColumn != null) ?
+ new SingleElementListIterable<JavaVirtualJoinColumn>(this.defaultInverseJoinColumn) :
+ EmptyListIterable.<JavaVirtualJoinColumn>instance();
+ }
+
+ protected int getDefaultInverseJoinColumnsSize() {
+ return (this.defaultInverseJoinColumn == null) ? 0 : 1;
+ }
+
+ protected void updateDefaultInverseJoinColumn() {
+ if (this.buildsDefaultInverseJoinColumn()) {
+ if (this.defaultInverseJoinColumn == null) {
+ this.setDefaultInverseJoinColumn(this.buildInverseJoinColumn(this.getOverriddenTable().getDefaultInverseJoinColumn()));
+ } else {
+ this.defaultInverseJoinColumn.update();
+ }
+ } else {
+ this.setDefaultInverseJoinColumn(null);
+ }
+ }
+
+ protected boolean buildsDefaultInverseJoinColumn() {
+ return ! this.hasSpecifiedInverseJoinColumns();
+ }
+
+
+ // ********** misc **********
+
+ @Override
+ public JavaVirtualJoinTableRelationshipStrategy getParent() {
+ return (JavaVirtualJoinTableRelationshipStrategy) super.getParent();
+ }
+
+ protected JavaVirtualJoinTableRelationshipStrategy getJoinStrategy() {
+ return this.getParent();
+ }
+
+ @Override
+ protected ReadOnlyJoinColumn.Owner buildJoinColumnOwner() {
+ return new JoinColumnOwner();
+ }
+
+ protected ReadOnlyJoinColumn.Owner buildInverseJoinColumnOwner() {
+ return new InverseJoinColumnOwner();
+ }
+
+ protected JavaVirtualJoinColumn buildInverseJoinColumn(JoinColumn joinColumn) {
+ return this.buildJoinColumn(this.inverseJoinColumnOwner, joinColumn);
+ }
+
+ @Override
+ protected String buildDefaultName() {
+ return this.getJoinStrategy().getJoinTableDefaultName();
+ }
+
+ public RelationshipMapping getRelationshipMapping() {
+ return this.getJoinStrategy().getRelationship().getMapping();
+ }
+
+ public PersistentAttribute getPersistentAttribute() {
+ return this.getRelationshipMapping().getPersistentAttribute();
+ }
+
+
+ // ********** join column owners **********
+
+ /**
+ * just a little common behavior
+ */
+ protected abstract class AbstractJoinColumnOwner
+ implements ReadOnlyJoinColumn.Owner
+ {
+ protected AbstractJoinColumnOwner() {
+ super();
+ }
+
+ public TypeMapping getTypeMapping() {
+ return this.getRelationship().getTypeMapping();
+ }
+
+ /**
+ * by default, the join column is, obviously, in the join table;
+ * not sure whether it can be anywhere else...
+ */
+ public String getDefaultTableName() {
+ return GenericJavaVirtualJoinTable.this.getName();
+ }
+
+ /**
+ * @see MappingTools#buildJoinColumnDefaultName(org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn, org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn.Owner)
+ */
+ public String getDefaultColumnName() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected JavaVirtualRelationship getRelationship() {
+ return GenericJavaVirtualJoinTable.this.getJoinStrategy().getRelationship();
+ }
+ }
+
+
+ /**
+ * owner for "back-pointer" join columns;
+ * these point at the source/owning entity
+ */
+ protected class JoinColumnOwner
+ extends AbstractJoinColumnOwner
+ {
+ protected JoinColumnOwner() {
+ super();
+ }
+
+ public Entity getRelationshipTarget() {
+ return this.getRelationship().getEntity();
+ }
+
+ public String getAttributeName() {
+ return MappingTools.getTargetAttributeName(GenericJavaVirtualJoinTable.this.getRelationshipMapping());
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return GenericJavaVirtualJoinTable.this.defaultJoinColumn == joinColumn;
+ }
+
+ public int joinColumnsSize() {
+ return GenericJavaVirtualJoinTable.this.joinColumnsSize();
+ }
+ }
+
+
+ /**
+ * owner for "forward-pointer" join columns;
+ * these point at the target/inverse entity
+ */
+ protected class InverseJoinColumnOwner
+ extends AbstractJoinColumnOwner
+ {
+ protected InverseJoinColumnOwner() {
+ super();
+ }
+
+ public Entity getRelationshipTarget() {
+ RelationshipMapping relationshipMapping = GenericJavaVirtualJoinTable.this.getRelationshipMapping();
+ return (relationshipMapping == null) ? null : relationshipMapping.getResolvedTargetEntity();
+ }
+
+ public String getAttributeName() {
+ RelationshipMapping relationshipMapping = GenericJavaVirtualJoinTable.this.getRelationshipMapping();
+ return (relationshipMapping == null) ? null : relationshipMapping.getName();
+ }
+
+ public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) {
+ return GenericJavaVirtualJoinTable.this.defaultInverseJoinColumn == joinColumn;
+ }
+
+ public int joinColumnsSize() {
+ return GenericJavaVirtualJoinTable.this.inverseJoinColumnsSize();
+ }
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBaseColumnTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBaseColumnTextRangeResolver.java
new file mode 100644
index 0000000000..951094aed6
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBaseColumnTextRangeResolver.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaBaseColumn;
+import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver;
+
+public class JavaBaseColumnTextRangeResolver
+ extends JavaNamedColumnTextRangeResolver
+ implements BaseColumnTextRangeResolver
+{
+
+ public JavaBaseColumnTextRangeResolver(JavaBaseColumn column, CompilationUnit astRoot) {
+ super(column, astRoot);
+ }
+
+ @Override
+ protected JavaBaseColumn getColumn() {
+ return (JavaBaseColumn) super.getColumn();
+ }
+ public TextRange getTableTextRange() {
+ return this.getColumn().getTableTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBasicMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBasicMappingDefinition.java
new file mode 100644
index 0000000000..7d13a41785
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaBasicMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
+
+public class JavaBasicMappingDefinition
+ extends AbstractJavaBasicMappingDefinition
+{
+ // singleton
+ private static final DefaultJavaAttributeMappingDefinition INSTANCE = new JavaBasicMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static DefaultJavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaBasicMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddableDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddableDefinition.java
new file mode 100644
index 0000000000..db5e442034
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddableDefinition.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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaEmbeddable;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMappingDefinition;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.EmbeddableAnnotation;
+
+public class JavaEmbeddableDefinition
+ implements JavaTypeMappingDefinition
+{
+ // singleton
+ private static final JavaEmbeddableDefinition INSTANCE = new JavaEmbeddableDefinition();
+
+ /**
+ * Return the singleton
+ */
+ public static JavaTypeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaEmbeddableDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.EMBEDDABLE_TYPE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return EmbeddableAnnotation.ANNOTATION_NAME;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return EmptyIterable.instance();
+ }
+
+ public JavaEmbeddable buildMapping(JavaPersistentType persistentType, Annotation mappingAnnotation, JpaFactory factory) {
+ return factory.buildJavaEmbeddable(persistentType, (EmbeddableAnnotation) mappingAnnotation);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedIdMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedIdMappingDefinition.java
new file mode 100644
index 0000000000..9695b24aca
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedIdMappingDefinition.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverrideAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverridesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.EmbeddedIdAnnotation;
+
+public class JavaEmbeddedIdMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaEmbeddedIdMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singletong usage
+ */
+ private JavaEmbeddedIdMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return EmbeddedIdAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ AttributeOverrideAnnotation.ANNOTATION_NAME,
+ AttributeOverridesAnnotation.ANNOTATION_NAME,
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaEmbeddedIdMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedMappingDefinition.java
new file mode 100644
index 0000000000..fc94ac724a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEmbeddedMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
+
+public class JavaEmbeddedMappingDefinition
+ extends AbstractJavaEmbeddedMappingDefinition
+{
+ // singleton
+ private static final DefaultJavaAttributeMappingDefinition INSTANCE = new JavaEmbeddedMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static DefaultJavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaEmbeddedMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityDefinition.java
new file mode 100644
index 0000000000..485e0b658b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityDefinition.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaEntity;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMappingDefinition;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.AssociationOverrideAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AssociationOverridesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverrideAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.AttributeOverridesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.DiscriminatorColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.DiscriminatorValueAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.EntityAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.IdClassAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.InheritanceAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JPA;
+import org.eclipse.jpt.jpa.core.resource.java.NamedNativeQueriesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.NamedNativeQueryAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.NamedQueriesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.NamedQueryAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnsAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SecondaryTableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SecondaryTablesAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.SequenceGeneratorAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TableAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.TableGeneratorAnnotation;
+
+public class JavaEntityDefinition
+ implements JavaTypeMappingDefinition
+{
+ // singleton
+ private static final JavaEntityDefinition INSTANCE = new JavaEntityDefinition();
+
+ /**
+ * Return the singleton
+ */
+ public static JavaTypeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaEntityDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.ENTITY_TYPE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return EntityAnnotation.ANNOTATION_NAME;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ TableAnnotation.ANNOTATION_NAME,
+ SecondaryTableAnnotation.ANNOTATION_NAME,
+ SecondaryTablesAnnotation.ANNOTATION_NAME,
+ PrimaryKeyJoinColumnAnnotation.ANNOTATION_NAME,
+ PrimaryKeyJoinColumnsAnnotation.ANNOTATION_NAME,
+ IdClassAnnotation.ANNOTATION_NAME,
+ InheritanceAnnotation.ANNOTATION_NAME,
+ DiscriminatorValueAnnotation.ANNOTATION_NAME,
+ DiscriminatorColumnAnnotation.ANNOTATION_NAME,
+ SequenceGeneratorAnnotation.ANNOTATION_NAME,
+ TableGeneratorAnnotation.ANNOTATION_NAME,
+ NamedQueryAnnotation.ANNOTATION_NAME,
+ NamedQueriesAnnotation.ANNOTATION_NAME,
+ NamedNativeQueryAnnotation.ANNOTATION_NAME,
+ NamedNativeQueriesAnnotation.ANNOTATION_NAME,
+ JPA.SQL_RESULT_SET_MAPPING,
+ JPA.EXCLUDE_DEFAULT_LISTENERS,
+ JPA.EXCLUDE_SUPERCLASS_LISTENERS,
+ JPA.ENTITY_LISTENERS,
+ JPA.PRE_PERSIST,
+ JPA.POST_PERSIST,
+ JPA.PRE_REMOVE,
+ JPA.POST_REMOVE,
+ JPA.PRE_UPDATE,
+ JPA.POST_UPDATE,
+ JPA.POST_LOAD,
+ AttributeOverrideAnnotation.ANNOTATION_NAME,
+ AttributeOverridesAnnotation.ANNOTATION_NAME,
+ AssociationOverrideAnnotation.ANNOTATION_NAME,
+ AssociationOverridesAnnotation.ANNOTATION_NAME
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaEntity buildMapping(JavaPersistentType persistentType, Annotation mappingAnnotation, JpaFactory factory) {
+ return factory.buildJavaEntity(persistentType, (EntityAnnotation) mappingAnnotation);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityTextRangeResolver.java
new file mode 100644
index 0000000000..af74224308
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaEntityTextRangeResolver.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaEntity;
+import org.eclipse.jpt.jpa.core.internal.context.EntityTextRangeResolver;
+
+public class JavaEntityTextRangeResolver
+ implements EntityTextRangeResolver
+{
+ private JavaEntity entity;
+
+ private CompilationUnit astRoot;
+
+
+ public JavaEntityTextRangeResolver(JavaEntity entity, CompilationUnit astRoot) {
+ this.entity = entity;
+ this.astRoot = astRoot;
+ }
+
+
+ public TextRange getTypeMappingTextRange() {
+ return this.entity.getValidationTextRange(this.astRoot);
+ }
+
+ public TextRange getIdClassTextRange() {
+ return this.entity.getIdClassReference().getValidationTextRange(this.astRoot);
+ }
+
+ public TextRange getAttributeMappingTextRange(String attributeName) {
+ return this.entity.getPersistentType().
+ getAttributeNamed(attributeName).getMapping().getValidationTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaIdMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaIdMappingDefinition.java
new file mode 100644
index 0000000000..1297324074
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaIdMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaIdMappingDefinition
+ extends AbstractJavaIdMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaIdMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaIdMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaJoinColumnTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaJoinColumnTextRangeResolver.java
new file mode 100644
index 0000000000..e715135955
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaJoinColumnTextRangeResolver.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn;
+import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver;
+
+public class JavaJoinColumnTextRangeResolver
+ extends JavaNamedColumnTextRangeResolver
+ implements JoinColumnTextRangeResolver
+{
+ public JavaJoinColumnTextRangeResolver(JavaJoinColumn column, CompilationUnit astRoot) {
+ super(column, astRoot);
+ }
+
+ @Override
+ protected JavaJoinColumn getColumn() {
+ return (JavaJoinColumn) super.getColumn();
+ }
+
+ public TextRange getTableTextRange() {
+ return this.getColumn().getTableTextRange(this.astRoot);
+ }
+
+ public TextRange getReferencedColumnNameTextRange() {
+ return this.getColumn().getReferencedColumnNameTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToManyMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToManyMappingDefinition.java
new file mode 100644
index 0000000000..dbce1decd9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToManyMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaManyToManyMappingDefinition
+ extends AbstractJavaManyToManyMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaManyToManyMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaManyToManyMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToOneMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToOneMappingDefinition.java
new file mode 100644
index 0000000000..f93744128a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaManyToOneMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaManyToOneMappingDefinition
+ extends AbstractJavaManyToOneMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaManyToOneMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaManyToOneMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassDefinition.java
new file mode 100644
index 0000000000..ce234ec00c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassDefinition.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedSuperclass;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMappingDefinition;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.jpt.jpa.core.resource.java.IdClassAnnotation;
+import org.eclipse.jpt.jpa.core.resource.java.JPA;
+import org.eclipse.jpt.jpa.core.resource.java.MappedSuperclassAnnotation;
+
+public class JavaMappedSuperclassDefinition
+ implements JavaTypeMappingDefinition
+{
+ // singleton
+ private static final JavaMappedSuperclassDefinition INSTANCE = new JavaMappedSuperclassDefinition();
+
+ /**
+ * Return the singleton
+ */
+ public static JavaTypeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaMappedSuperclassDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.MAPPED_SUPERCLASS_TYPE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return MappedSuperclassAnnotation.ANNOTATION_NAME;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return SUPPORTING_ANNOTATION_NAMES;
+ }
+
+ protected static final String[] SUPPORTING_ANNOTATION_NAMES_ARRAY = new String[] {
+ IdClassAnnotation.ANNOTATION_NAME,
+ JPA.EXCLUDE_DEFAULT_LISTENERS,
+ JPA.EXCLUDE_SUPERCLASS_LISTENERS,
+ JPA.ENTITY_LISTENERS,
+ JPA.PRE_PERSIST,
+ JPA.POST_PERSIST,
+ JPA.PRE_REMOVE,
+ JPA.POST_REMOVE,
+ JPA.PRE_UPDATE,
+ JPA.POST_UPDATE,
+ JPA.POST_LOAD
+ };
+ protected static final Iterable<String> SUPPORTING_ANNOTATION_NAMES = new ArrayIterable<String>(SUPPORTING_ANNOTATION_NAMES_ARRAY);
+
+ public JavaMappedSuperclass buildMapping(JavaPersistentType persistentType, Annotation mappingAnnotation, JpaFactory factory) {
+ return factory.buildJavaMappedSuperclass(persistentType, (MappedSuperclassAnnotation) mappingAnnotation);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassTextRangeResolver.java
new file mode 100644
index 0000000000..c9319716ea
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaMappedSuperclassTextRangeResolver.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaMappedSuperclass;
+import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver;
+
+public class JavaMappedSuperclassTextRangeResolver
+ implements PrimaryKeyTextRangeResolver
+{
+ private JavaMappedSuperclass mappedSuperclass;
+
+ private CompilationUnit astRoot;
+
+
+ public JavaMappedSuperclassTextRangeResolver(
+ JavaMappedSuperclass mappedSuperclass, CompilationUnit astRoot) {
+
+ this.mappedSuperclass = mappedSuperclass;
+ this.astRoot = astRoot;
+ }
+
+
+ public TextRange getTypeMappingTextRange() {
+ return this.mappedSuperclass.getValidationTextRange(this.astRoot);
+ }
+
+ public TextRange getIdClassTextRange() {
+ return this.mappedSuperclass.getIdClassReference().getValidationTextRange(this.astRoot);
+ }
+
+ public TextRange getAttributeMappingTextRange(String attributeName) {
+ return this.mappedSuperclass.getPersistentType().
+ getAttributeNamed(attributeName).getMapping().getValidationTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNamedColumnTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNamedColumnTextRangeResolver.java
new file mode 100644
index 0000000000..cab6e08e67
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNamedColumnTextRangeResolver.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaNamedColumn;
+import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver;
+
+public class JavaNamedColumnTextRangeResolver
+ implements NamedColumnTextRangeResolver
+{
+ protected final JavaNamedColumn javaNamedColumn;
+
+ protected final CompilationUnit astRoot;
+
+ public JavaNamedColumnTextRangeResolver(JavaNamedColumn javaNamedColumn, CompilationUnit astRoot) {
+ this.javaNamedColumn = javaNamedColumn;
+ this.astRoot = astRoot;
+ }
+
+ protected JavaNamedColumn getColumn() {
+ return this.javaNamedColumn;
+ }
+
+ public TextRange getNameTextRange() {
+ return this.javaNamedColumn.getNameTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNullTypeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNullTypeMapping.java
new file mode 100644
index 0000000000..b48a3deef0
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaNullTypeMapping.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import java.util.List;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.resource.java.Annotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+
+/**
+ * Java null type mapping
+ */
+public class JavaNullTypeMapping
+ extends AbstractJavaTypeMapping<Annotation>
+{
+ public JavaNullTypeMapping(JavaPersistentType parent) {
+ super(parent, null);
+ }
+
+ public String getKey() {
+ return MappingKeys.NULL_TYPE_MAPPING_KEY;
+ }
+
+ public JavaPersistentType getIdClass() {
+ return null;
+ }
+
+ public boolean isMapped() {
+ return false;
+ }
+
+ public boolean tableNameIsInvalid(String tableName) {
+ return false;
+ }
+
+
+ // ********** validation **********
+
+ /**
+ * We added this message here because the most likely solution is to add
+ * an annotation to the .java file.
+ * This message used to be found on the <class> tag in persistence.xml.
+ * The other possible way to fix the error is to remove it from persistence.xml.
+ * This can be accomplished with the Synchronize Classes action.
+ * We could also add a quick fix for this error.
+ */
+ @Override
+ public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+ super.validate(messages, reporter, astRoot);
+ messages.add(
+ DefaultJpaValidationMessages.buildMessage(
+ IMessage.HIGH_SEVERITY,
+ JpaValidationMessages.PERSISTENCE_UNIT_INVALID_CLASS,
+ new String[] {this.getPersistentType().getName()},
+ this,
+ this.getValidationTextRange(astRoot)
+ )
+ );
+ }
+
+ @Override
+ public boolean validatesAgainstDatabase() {
+ return false;
+ }
+
+ @Override
+ public TextRange getValidationTextRange(CompilationUnit astRoot) {
+ return this.getPersistentType().getValidationTextRange(astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToManyMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToManyMappingDefinition.java
new file mode 100644
index 0000000000..e2029a4f07
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToManyMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaOneToManyMappingDefinition
+ extends AbstractJavaOneToManyMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaOneToManyMappingDefinition();
+
+ /**
+ * Return the singleton
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaOneToManyMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToOneMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToOneMappingDefinition.java
new file mode 100644
index 0000000000..6ed2d0b317
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOneToOneMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaOneToOneMappingDefinition
+ extends AbstractJavaOneToOneMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaOneToOneMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaOneToOneMappingDefinition() {
+ super();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOverrideTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOverrideTextRangeResolver.java
new file mode 100644
index 0000000000..7dcd7ce470
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaOverrideTextRangeResolver.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaOverride;
+import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver;
+
+public class JavaOverrideTextRangeResolver
+ implements OverrideTextRangeResolver
+{
+ protected final JavaOverride javaOverride;
+
+ protected final CompilationUnit astRoot;
+
+ public JavaOverrideTextRangeResolver(JavaOverride javaOverride, CompilationUnit astRoot) {
+ this.javaOverride = javaOverride;
+ this.astRoot = astRoot;
+ }
+
+ protected JavaOverride getOverride() {
+ return this.javaOverride;
+ }
+
+ public TextRange getNameTextRange() {
+ return this.javaOverride.getNameTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPersistentAttributeTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPersistentAttributeTextRangeResolver.java
new file mode 100644
index 0000000000..83fe6f95ca
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPersistentAttributeTextRangeResolver.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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.internal.context.PersistentAttributeTextRangeResolver;
+
+public class JavaPersistentAttributeTextRangeResolver
+ implements PersistentAttributeTextRangeResolver
+{
+ private JavaPersistentAttribute javaPersistentAttribute;
+
+ private CompilationUnit astRoot;
+
+ public JavaPersistentAttributeTextRangeResolver(JavaPersistentAttribute javaPersistentAttribute, CompilationUnit astRoot) {
+ this.javaPersistentAttribute = javaPersistentAttribute;
+ this.astRoot = astRoot;
+ }
+
+ public TextRange getAttributeTextRange() {
+ return this.javaPersistentAttribute.getValidationTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPrimaryKeyJoinColumnTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPrimaryKeyJoinColumnTextRangeResolver.java
new file mode 100644
index 0000000000..261f522f4a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaPrimaryKeyJoinColumnTextRangeResolver.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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn;
+import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver;
+
+public class JavaPrimaryKeyJoinColumnTextRangeResolver
+ extends JavaNamedColumnTextRangeResolver
+ implements BaseJoinColumnTextRangeResolver
+{
+
+ public JavaPrimaryKeyJoinColumnTextRangeResolver(JavaPrimaryKeyJoinColumn column, CompilationUnit astRoot) {
+ super(column, astRoot);
+ }
+
+ @Override
+ protected JavaPrimaryKeyJoinColumn getColumn() {
+ return (JavaPrimaryKeyJoinColumn) super.getColumn();
+ }
+
+ public TextRange getReferencedColumnNameTextRange() {
+ return this.getColumn().getReferencedColumnNameTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTableTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTableTextRangeResolver.java
new file mode 100644
index 0000000000..2f431635bb
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTableTextRangeResolver.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaTable;
+import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver;
+
+public class JavaTableTextRangeResolver
+ implements TableTextRangeResolver
+{
+ protected final JavaTable javaTable;
+
+ protected final CompilationUnit astRoot;
+
+ public JavaTableTextRangeResolver(JavaTable javaTable, CompilationUnit astRoot) {
+ this.javaTable = javaTable;
+ this.astRoot = astRoot;
+ }
+
+ protected JavaTable getTable() {
+ return this.javaTable;
+ }
+
+ public TextRange getNameTextRange() {
+ return this.javaTable.getNameTextRange(this.astRoot);
+ }
+
+ public TextRange getCatalogTextRange() {
+ return this.javaTable.getCatalogTextRange(this.astRoot);
+ }
+
+ public TextRange getSchemaTextRange() {
+ return this.javaTable.getSchemaTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTransientMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTransientMappingDefinition.java
new file mode 100644
index 0000000000..4618a9ec32
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTransientMappingDefinition.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.jpa.core.JpaFactory;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.resource.java.TransientAnnotation;
+
+public class JavaTransientMappingDefinition
+ implements JavaAttributeMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaTransientMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaTransientMappingDefinition() {
+ super();
+ }
+
+ public String getKey() {
+ return MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY;
+ }
+
+ public String getAnnotationName() {
+ return TransientAnnotation.ANNOTATION_NAME;
+ }
+
+ public boolean isSpecified(JavaPersistentAttribute persistentAttribute) {
+ return persistentAttribute.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()) != null;
+ }
+
+ public Iterable<String> getSupportingAnnotationNames() {
+ return EmptyIterable.instance();
+ }
+
+ public JavaAttributeMapping buildMapping(JavaPersistentAttribute persistentAttribute, JpaFactory factory) {
+ return factory.buildJavaTransientMapping(persistentAttribute);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTypeMappingTextRangeResolver.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTypeMappingTextRangeResolver.java
new file mode 100644
index 0000000000..174e6b2b7a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaTypeMappingTextRangeResolver.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.jpa.core.internal.context.java;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTextRangeResolver;
+
+public class JavaTypeMappingTextRangeResolver
+ implements TypeMappingTextRangeResolver
+{
+ private JavaTypeMapping typeMapping;
+
+ private CompilationUnit astRoot;
+
+ public JavaTypeMappingTextRangeResolver(JavaTypeMapping typeMapping, CompilationUnit astRoot) {
+ this.typeMapping = typeMapping;
+ this.astRoot = astRoot;
+ }
+
+ public TextRange getTypeMappingTextRange() {
+ return this.typeMapping.getValidationTextRange(this.astRoot);
+ }
+}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaVersionMappingDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaVersionMappingDefinition.java
new file mode 100644
index 0000000000..c078d6fced
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/java/JavaVersionMappingDefinition.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.jpa.core.internal.context.java;
+
+import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
+
+public class JavaVersionMappingDefinition
+ extends AbstractJavaVersionMappingDefinition
+{
+ // singleton
+ private static final JavaAttributeMappingDefinition INSTANCE = new JavaVersionMappingDefinition();
+
+ /**
+ * Return the singleton.
+ */
+ public static JavaAttributeMappingDefinition instance() {
+ return INSTANCE;
+ }
+
+
+ /**
+ * Enforce singleton usage
+ */
+ private JavaVersionMappingDefinition() {
+ super();
+ }
+}

Back to the top