diff options
author | kmoore | 2011-02-06 02:07:28 +0000 |
---|---|---|
committer | kmoore | 2011-02-06 02:07:28 +0000 |
commit | c9c9e2b3e236ad701f642b72bca0cfabcac1d97b (patch) | |
tree | 346196323dc94395c2348339ac67e4f4cec6ebbf /jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context | |
parent | 8f2746f6b8c2ddc81d653d54d280043c41ed4734 (diff) | |
download | webtools.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/jpa1/context')
170 files changed, 24904 insertions, 0 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java new file mode 100644 index 0000000000..159df40278 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractEntityPrimaryKeyValidator.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2011 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import java.util.List; + +import org.eclipse.jpt.jpa.core.context.AttributeMapping; +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.IdClassReference; +import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractEntityPrimaryKeyValidator extends + AbstractPrimaryKeyValidator { + + public AbstractEntityPrimaryKeyValidator(Entity entity, + PrimaryKeyTextRangeResolver textRangeResolver) { + super(entity, textRangeResolver); + } + + protected Entity entity() { + return (Entity) this.typeMapping(); + } + + @Override + protected IdClassReference idClassReference() { + return entity().getIdClassReference(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + // if an entity is non-root, it is not allowed to define primary keys + if (! entity().isRoot()) { + validatePrimaryKeyForNonRoot(messages, reporter); + } + else { + validatePrimaryKeyForRoot(messages, reporter); + } + return true; + } + + protected void validatePrimaryKeyForNonRoot(List<IMessage> messages, IReporter reporter) { + validateNonRootEntityDoesNotSpecifyIdClass(messages, reporter); + validateNonRootEntityDoesNotSpecifyPrimaryKeyAttributes(messages, reporter); + } + + protected void validatePrimaryKeyForRoot(List<IMessage> messages, IReporter reporter) { + validatePrimaryKeyIsNotRedefined(messages, reporter); + validateIdClassIsUsedIfNecessary(messages, reporter); + + // if the primary key is not defined on an ancestor, it must be defined here + if (! definesPrimaryKey(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NO_PK, + EMPTY_STRING_ARRAY, + entity(), + textRangeResolver().getTypeMappingTextRange())); + } + + // if primary key is composite, it may either use an id class or embedded id, not both + validateOneOfIdClassOrEmbeddedIdIsUsed(messages, reporter); + // ... and only one embedded id + validateOneEmbeddedId(messages, reporter); + + validateMapsIdMappings(messages, reporter); + + if (specifiesIdClass()) { + validateIdClass(idClassReference().getIdClass(), messages, reporter); + } + } + + protected void validateNonRootEntityDoesNotSpecifyIdClass(List<IMessage> messages, IReporter reporter) { + if (idClassReference().isSpecified()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NON_ROOT_ID_CLASS_SPECIFIED, + EMPTY_STRING_ARRAY, + entity(), + textRangeResolver().getIdClassTextRange())); + } + } + + protected void validateNonRootEntityDoesNotSpecifyPrimaryKeyAttributes(List<IMessage> messages, IReporter reporter) { + for (AttributeMapping each : getPrimaryKeyMappingsDefinedLocally(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ENTITY_NON_ROOT_ID_ATTRIBUTE_SPECIFIED, + EMPTY_STRING_ARRAY, + each, + textRangeResolver().getAttributeMappingTextRange(each.getName()))); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractJoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractJoinTableValidator.java new file mode 100644 index 0000000000..58e53d7f21 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractJoinTableValidator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public abstract class AbstractJoinTableValidator extends AbstractTableValidator +{ + protected AbstractJoinTableValidator(JoinTable table, TableTextRangeResolver textRangeResolver) { + super(table, textRangeResolver); + } + + protected AbstractJoinTableValidator(PersistentAttribute persistentAttribute, JoinTable table, TableTextRangeResolver textRangeResolver) { + super(persistentAttribute, table, textRangeResolver); + } + + @Override + protected String getUnresolvedCatalogMessage() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getUnresolvedSchemaMessage() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java new file mode 100644 index 0000000000..37552dc286 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractMappedSuperclassPrimaryKeyValidator.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2011 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.IdClassReference; +import org.eclipse.jpt.jpa.core.context.MappedSuperclass; +import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractMappedSuperclassPrimaryKeyValidator + extends AbstractPrimaryKeyValidator +{ + public AbstractMappedSuperclassPrimaryKeyValidator( + MappedSuperclass mappedSuperclass, PrimaryKeyTextRangeResolver textRangeResolver) { + + super(mappedSuperclass, textRangeResolver); + } + + + protected MappedSuperclass mappedSuperclass() { + return (MappedSuperclass) this.typeMapping(); + } + + @Override + protected IdClassReference idClassReference() { + return mappedSuperclass().getIdClassReference(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + validatePrimaryKeyIsNotRedefined(messages, reporter); + validateIdClassIsUsedIfNecessary(messages, reporter); + + // if primary key is composite, it may either use an id class or embedded id, not both + validateOneOfIdClassOrEmbeddedIdIsUsed(messages, reporter); + // ... and only one embedded id + validateOneEmbeddedId(messages, reporter); + + if (specifiesIdClass()) { + validateIdClass(idClassReference().getIdClass(), messages, reporter); + } + return true; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractNamedColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractNamedColumnValidator.java new file mode 100644 index 0000000000..81080e19ba --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractNamedColumnValidator.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +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.BaseColumnTableValidator.NullTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +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 AbstractNamedColumnValidator<C extends NamedColumn, R extends NamedColumnTextRangeResolver> + implements JptValidator +{ + protected final PersistentAttribute persistentAttribute; + + protected final C column; + + protected final R textRangeResolver; + + protected final TableValidator tableValidator; + + protected final TableDescriptionProvider tableDescriptionProvider; + + protected AbstractNamedColumnValidator( + C column, + R textRangeResolver) { + this(null, column, textRangeResolver); + } + + protected AbstractNamedColumnValidator( + C column, + R textRangeResolver, + TableDescriptionProvider provider) { + this(null, column, textRangeResolver, provider); + } + + protected AbstractNamedColumnValidator( + PersistentAttribute persistentAttribute, + C column, + R textRangeResolver) { + this(persistentAttribute, column, textRangeResolver, new NullTableDescriptionProvider()); + } + + protected AbstractNamedColumnValidator( + PersistentAttribute persistentAttribute, + C column, + R textRangeResolver, + TableDescriptionProvider provider) { + this.persistentAttribute = persistentAttribute; + this.column = column; + this.textRangeResolver = textRangeResolver; + this.tableDescriptionProvider = provider; + this.tableValidator = this.buildTableValidator(); + } + + protected TableValidator buildTableValidator() { + return new NullTableValidator(); + } + + protected boolean isPersistentAttributeVirtual() { + return (this.persistentAttribute != null) && this.persistentAttribute.isVirtual(); + } + + protected String getPersistentAttributeName() { + return this.persistentAttribute.getName(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + if (this.tableValidator.tableNameIsInvalid()) { + return this.tableValidator.validate(messages, reporter); + } + this.validateName(messages); + return true; + } + + protected void validateName(List<IMessage> messages) { + Table dbTable = this.column.getDbTable(); + if ((dbTable != null) && ! this.column.isResolved()) { + messages.add(this.buildUnresolvedNameMessage()); + } + } + + protected IMessage buildUnresolvedNameMessage() { + return this.isPersistentAttributeVirtual() ? + this.buildVirtualAttributeUnresolvedNameMessage() : + this.buildUnresolvedNameMessage(this.getUnresolvedNameMessage()); + } + + protected IMessage buildUnresolvedNameMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] { + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getUnresolvedNameMessage(); + + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedNameMessage(); + + + // ********** table validator ********** + + public interface TableValidator + extends JptValidator + { + boolean tableNameIsInvalid(); + } + + public static class NullTableValidator + implements TableValidator + { + public boolean validate(List<IMessage> messages, IReporter reporter) { + return true; + } + public boolean tableNameIsInvalid() { + return false; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java new file mode 100644 index 0000000000..b62e5a415f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPersistentAttributeValidator.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.PersistentAttributeTextRangeResolver; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractPersistentAttributeValidator + implements JptValidator +{ + protected PersistentAttribute persistentAttribute; + + protected JavaPersistentAttribute javaPersistentAttribute; + + protected PersistentAttributeTextRangeResolver textRangeResolver; + + + protected AbstractPersistentAttributeValidator( + PersistentAttribute persistentAttribute, JavaPersistentAttribute javaPersistentAttribute, PersistentAttributeTextRangeResolver textRangeResolver) { + this.persistentAttribute = persistentAttribute; + this.javaPersistentAttribute = javaPersistentAttribute; + this.textRangeResolver = textRangeResolver; + } + + + public boolean validate(List<IMessage> messages, IReporter reporter) { + this.validateAttribute(messages); + return true; + } + + protected abstract void validateAttribute(List<IMessage> messages); + + protected boolean isFieldAttribute() { + if (this.javaPersistentAttribute == null) { + return false; + } + return this.javaPersistentAttribute.isField(); + } + + protected boolean isPropertyAttribute() { + if (this.javaPersistentAttribute == null) { + return false; + } + return this.javaPersistentAttribute.isProperty(); + } + + protected boolean isFinalAttribute() { + if (this.javaPersistentAttribute == null) { + return false; + } + return this.javaPersistentAttribute.isFinal(); + } + + protected boolean isPublicAttribute() { + if (this.javaPersistentAttribute == null) { + return false; + } + return this.javaPersistentAttribute.isPublic(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java new file mode 100644 index 0000000000..4c3f9fd870 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractPrimaryKeyValidator.java @@ -0,0 +1,618 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.common.utility.internal.ClassName; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.HashBag; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable; +import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SubIterableWrapper; +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.AttributeMapping; +import org.eclipse.jpt.jpa.core.context.EmbeddedIdMapping; +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.IdClassReference; +import org.eclipse.jpt.jpa.core.context.IdMapping; +import org.eclipse.jpt.jpa.core.context.ReadOnlyPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +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.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.jpa.core.jpa2.context.SingleRelationshipMapping2_0; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractPrimaryKeyValidator + implements JptValidator +{ + private TypeMapping typeMapping; + + private PrimaryKeyTextRangeResolver textRangeResolver; + + public static final String[] EMPTY_STRING_ARRAY = StringTools.EMPTY_STRING_ARRAY; + + protected AbstractPrimaryKeyValidator( + TypeMapping typeMapping, PrimaryKeyTextRangeResolver textRangeResolver) { + + this.typeMapping = typeMapping; + this.textRangeResolver = textRangeResolver; + } + + + protected TypeMapping typeMapping() { + return this.typeMapping; + } + + protected abstract IdClassReference idClassReference(); + + protected PrimaryKeyTextRangeResolver textRangeResolver() { + return this.textRangeResolver; + } + + // for JPA portability, a hierarchy must define its primary key on one class + // (entity *or* mapped superclass) + protected void validatePrimaryKeyIsNotRedefined(List<IMessage> messages, IReporter reporter) { + if (definesPrimaryKeyOnAncestor(typeMapping())) { + if (idClassReference().isSpecified()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_CLASS, + EMPTY_STRING_ARRAY, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + for (AttributeMapping each : getPrimaryKeyMappingsDefinedLocally(typeMapping())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_ATTRIBUTE, + EMPTY_STRING_ARRAY, + each, + textRangeResolver().getAttributeMappingTextRange(each.getName()))); + } + return; + } + } + + // if a primary key defining class has multiple primary keys, it must use an id class + protected void validateIdClassIsUsedIfNecessary(List<IMessage> messages, IReporter reporter) { + if (! specifiesIdClass() && idClassIsRequired()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_REQUIRED, + EMPTY_STRING_ARRAY, + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + // only one composite primary key strategy may be used + protected void validateOneOfIdClassOrEmbeddedIdIsUsed(List<IMessage> messages, IReporter reporter) { + if (idClassReference().isSpecified() + && CollectionTools.size(typeMapping().getAllAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)) > 0) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_AND_EMBEDDED_ID_BOTH_USED, + EMPTY_STRING_ARRAY, + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + // only one embedded id may be used + protected void validateOneEmbeddedId(List<IMessage> messages, IReporter reporter) { + if (CollectionTools.size(getEmbeddedIdMappings(typeMapping())) > 1) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_MULTIPLE_EMBEDDED_ID, + EMPTY_STRING_ARRAY, + typeMapping(), + textRangeResolver().getTypeMappingTextRange())); + } + } + + protected void validateMapsIdMappings(List<IMessage> messages, IReporter reporter) { + for (SingleRelationshipMapping2_0 mapsIdRelationshipMapping : getMapsIdMappingsDefinedLocally(typeMapping())) { + // can't use maps id mappings with an id class + if (definesIdClass(typeMapping())) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_WITH_MAPS_ID, + new String[] {mapsIdRelationshipMapping.getName()}, + mapsIdRelationshipMapping, + textRangeResolver().getAttributeMappingTextRange(mapsIdRelationshipMapping.getName()))); + } + + AttributeMapping resolvedAttributeMapping = + mapsIdRelationshipMapping.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getResolvedAttributeMappingValue(); + if (resolvedAttributeMapping != null + && ! ClassName.areAutoboxEquivalents( + resolvedAttributeMapping.getPersistentAttribute().getTypeName(), + getTargetEntityPrimaryKeyTypeName(mapsIdRelationshipMapping))) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_MAPS_ID_ATTRIBUTE_TYPE_DOES_NOT_AGREE, + new String[] {mapsIdRelationshipMapping.getName()}, + mapsIdRelationshipMapping, + textRangeResolver().getAttributeMappingTextRange(mapsIdRelationshipMapping.getName()))); + } + } + } + + protected void validateIdClass(JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) { + // there should already be a validation error if the id class does not resolve to a class + if (idClass == null) { + return; + } + + if (hasDerivedIdMappingMatchingIdClass(idClass)) { + validateIdClass_derivedIdMappingMatchingIdClass(idClass, messages, reporter); + return; + } + for (JavaPersistentAttribute idClassAttribute : + new SubIterableWrapper<ReadOnlyPersistentAttribute, JavaPersistentAttribute>( + CollectionTools.iterable(idClass.allAttributes()))) { + boolean foundMatch = false; + for (AttributeMapping attributeMapping : getAttributeMappings(typeMapping())) { + if (idClassAttribute.getName().equals(attributeMapping.getName())) { + foundMatch = true; + + // the matching attribute should be a primary key + if (! definesPrimaryKey(attributeMapping)) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NOT_PRIMARY_KEY, + new String[] {idClassAttribute.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + // the matching attribute's type should agree + String idClassAttributeTypeName = idClassAttribute.getTypeName(); + String attributeMappingTypeName = getTypeNameForIdClass(attributeMapping); + if (attributeMappingTypeName != null // if it's null, there should be + // another failing validation elsewhere + && ! ClassName.areAutoboxEquivalents(idClassAttributeTypeName, attributeMappingTypeName)) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_TYPE_DOES_NOT_AGREE, + new String[] {idClassAttribute.getName(), idClassAttributeTypeName}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + } + } + + if (! foundMatch) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NO_MATCH, + new String[] {idClassAttribute.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + } + } + + protected void validateIdClass_derivedIdMappingMatchingIdClass( + JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) { + + Collection<AttributeMapping> errorMappings = new HashBag<AttributeMapping>(); + for (AttributeMapping each + : new CompositeIterable<AttributeMapping>(getIdMappings(typeMapping()), getEmbeddedIdMappings(typeMapping()))) { + errorMappings.add(each); + } + Collection<AttributeMapping> errorDerivedIdMappings = new HashBag<AttributeMapping>(); + for (SingleRelationshipMapping2_0 each : getDerivedIdMappings(typeMapping())) { + if (idClass.getName().equals(getTargetEntityPrimaryKeyTypeName(each))) { + errorDerivedIdMappings.add(each); + } + else { + errorMappings.add(each); + } + } + for (AttributeMapping each : errorMappings) { + addNoIdClassAttributeMatchError(each, messages); + } + if (CollectionTools.size(errorDerivedIdMappings) > 1) { + for (AttributeMapping each : errorDerivedIdMappings) { + addDuplicateIdClassAttributeMatchError(each, messages); + } + } + } + + protected void addNoIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_NO_MATCH, + new String[] {attributeMapping.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + protected void addDuplicateIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) { + messages.add(DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_DUPLICATE_MATCH, + new String[] {attributeMapping.getName()}, + typeMapping(), + textRangeResolver().getIdClassTextRange())); + } + + + // **************** convenience methods ******************************************************** + + // **************** primary key overall ******************************************************** + + /** + * Return whether an ancestor class has defined any aspect of the primary key + */ + protected boolean definesPrimaryKeyOnAncestor(TypeMapping typeMapping) { + for (TypeMapping each : CollectionTools.iterable(typeMapping.inheritanceHierarchy())) { + if (each != typeMapping && definesPrimaryKey(each)) { + return true; + } + } + return false; + } + + /** + * Return whether the type mapping has defined any aspect of the primary key + */ + protected boolean definesPrimaryKey(TypeMapping typeMapping) { + return getIdClass(typeMapping) != null + || ! CollectionTools.isEmpty(getPrimaryKeyMappings(typeMapping)); + } + + /** + * Return true if the type mapping has defined any aspect of a complex primary key + */ + protected boolean definesComplexPrimaryKey(TypeMapping typeMapping) { + return definesIdClass(typeMapping) + || getEmbeddedIdMapping(typeMapping) != null; + } + + /** + * Return the overriding type name of the primary key for the type mapping. + * This may be + * - type of the single simple primary key (id) attribute + * - type of the single complex primary key (embedded id) attribute + * - type of the id class + * - null if none of the above are coherent (i.e. there are multiple possibilities, or the + * primary key is invalid) + */ + protected String getPrimaryKeyTypeName(TypeMapping typeMapping) { + JavaPersistentType idClass = getIdClass(typeMapping); + if (idClass != null) { + return idClass.getName(); + } + EmbeddedIdMapping embeddedId = getEmbeddedIdMapping(typeMapping); + if (embeddedId != null) { + return embeddedId.getPersistentAttribute().getTypeName(); + } + IdMapping id = getIdMapping(typeMapping); + if (id != null) { + return id.getPersistentAttribute().getTypeName(); + } + return null; + } + + /** + * Return whether the attribute mapping has defined any aspect of the primary key + */ + protected boolean definesPrimaryKey(AttributeMapping attributeMapping) { + String mappingKey = attributeMapping.getKey(); + if (CollectionTools.contains(this.getIdMappingKeys(), mappingKey)) { + return true; + } + if (CollectionTools.contains(this.getSingleRelationshipMappingKeys(), mappingKey)) { + SingleRelationshipMapping2_0 relationshipMapping = (SingleRelationshipMapping2_0) attributeMapping; + return (relationshipMapping.getDerivedIdentity().usesIdDerivedIdentityStrategy() + || relationshipMapping.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy()); + } + return false; + } + + protected Iterable<String> getIdMappingKeys() { + return ID_MAPPING_KEYS; + } + + protected static final String[] ID_MAPPING_KEYS_ARRAY = new String[] { + MappingKeys.ID_ATTRIBUTE_MAPPING_KEY, + MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY + }; + + protected static final Iterable<String> ID_MAPPING_KEYS = new ArrayIterable<String>(ID_MAPPING_KEYS_ARRAY); + + protected Iterable<String> getSingleRelationshipMappingKeys() { + return SINGLE_RELATIONSHIP_MAPPING_KEYS; + } + + protected static final String[] SINGLE_RELATIONSHIP_MAPPING_KEYS_ARRAY = new String[] { + MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY, + MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY + }; + + protected static final Iterable<String> SINGLE_RELATIONSHIP_MAPPING_KEYS = new ArrayIterable<String>(SINGLE_RELATIONSHIP_MAPPING_KEYS_ARRAY); + + + // **************** id class ********************************************** + + protected boolean specifiesIdClass() { + return idClassReference().isSpecified(); + } + + /** + * Return whether an id class is defined on the class + * NOTE: this is different from whether an id class is *specified*. If a specified id class + * is not resolved, it is not defined. There will be a validation error to that effect. + */ + protected boolean definesIdClass(TypeMapping typeMapping) { + return getIdClass(typeMapping) != null; + } + + /** + * Return whether an ancestor class has defined an id class + */ + protected boolean definesIdClassOnAncestor(TypeMapping typeMapping) { + for (TypeMapping each : CollectionTools.iterable(typeMapping.inheritanceHierarchy())) { + if (each != typeMapping && definesIdClass(each)) { + return true; + } + } + return false; + } + + /** + * Return the id class to be used for the type mapping, whether that be locally + * or on an ancestor + */ + protected JavaPersistentType getIdClass(TypeMapping typeMapping) { + for (Iterator<TypeMapping> stream = typeMapping.inheritanceHierarchy(); stream.hasNext(); ) { + TypeMapping next = stream.next(); + if (next.getIdClass() != null) { + return next.getIdClass(); + } + } + return null; + } + + + // **************** attribute mappings in general ************************* + + protected Iterable<AttributeMapping> getAttributeMappings(TypeMapping typeMapping) { + return CollectionTools.collection(typeMapping.allAttributeMappings()); + } + + /** + * Return all primary key mappings, defined on and above the type mapping + */ + protected Iterable<AttributeMapping> getPrimaryKeyMappings(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + getIdMappings(typeMapping), + getEmbeddedIdMappings(typeMapping), + getDerivedIdMappings(typeMapping), + getMapsIdMappings(typeMapping)); + } + + /** + * Return primary key mappings declared directly on the type mapping + */ + protected Iterable<AttributeMapping> getPrimaryKeyMappingsDefinedLocally(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + getIdMappingsDefinedLocally(typeMapping), + getEmbeddedIdMappingsDefinedLocally(typeMapping), + getDerivedIdMappingsDefinedLocally(typeMapping), + getMapsIdMappingsDefinedLocally(typeMapping)); + } + + protected boolean hasAnyPrimaryKeyMappings(TypeMapping typeMapping) { + return ! CollectionTools.isEmpty(getPrimaryKeyMappings(typeMapping)); + } + + // **************** id mappings ******************************************* + + protected IdMapping getIdMapping(TypeMapping typeMapping) { + Iterable<IdMapping> idMappings = getIdMappings(typeMapping); + if (CollectionTools.size(idMappings) == 1) { + return idMappings.iterator().next(); + } + return null; + } + + protected Iterable<IdMapping> getIdMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, IdMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY)); + } + + protected Iterable<IdMapping> getIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, IdMapping>( + typeMapping.getAttributeMappings(MappingKeys.ID_ATTRIBUTE_MAPPING_KEY)); + } + + + // **************** embedded id mappings ********************************** + + /** + * Return whether an embedded id is defined for this class, whether that be locally + * or on an ancestor + */ + protected boolean definesEmbeddedIdMapping(TypeMapping typeMapping) { + return ! CollectionTools.isEmpty(getEmbeddedIdMappings(typeMapping)); + } + + protected EmbeddedIdMapping getEmbeddedIdMapping(TypeMapping typeMapping) { + Iterable<EmbeddedIdMapping> embeddedIdMappings = getEmbeddedIdMappings(typeMapping); + if (CollectionTools.size(embeddedIdMappings) == 1) { + return embeddedIdMappings.iterator().next(); + } + return null; + } + + protected Iterable<EmbeddedIdMapping> getEmbeddedIdMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, EmbeddedIdMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)); + } + + protected Iterable<EmbeddedIdMapping> getEmbeddedIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, EmbeddedIdMapping>( + typeMapping.getAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)); + } + + + // **************** derived id mappings *********************************** + + protected Iterable<SingleRelationshipMapping2_0> getDerivedIdMappings(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>(this.getAllSingleRelationshipMappings(typeMapping)) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesIdDerivedIdentityStrategy(); + } + }; + } + + protected Iterable<SingleRelationshipMapping2_0> getAllSingleRelationshipMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>(this.getAllSingleRelationshipMappings_(typeMapping)); + } + + @SuppressWarnings("unchecked") + protected Iterable<AttributeMapping> getAllSingleRelationshipMappings_(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + typeMapping.getAllAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAllAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) + ); + } + + protected Iterable<SingleRelationshipMapping2_0> getDerivedIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>(this.getSingleRelationshipMappings(typeMapping)) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesIdDerivedIdentityStrategy(); + } + }; + } + + protected Iterable<SingleRelationshipMapping2_0> getSingleRelationshipMappings(TypeMapping typeMapping) { + return new SubIterableWrapper<AttributeMapping, SingleRelationshipMapping2_0>(this.getSingleRelationshipMappings_(typeMapping)); + } + + @SuppressWarnings("unchecked") + protected Iterable<AttributeMapping> getSingleRelationshipMappings_(TypeMapping typeMapping) { + return new CompositeIterable<AttributeMapping>( + typeMapping.getAttributeMappings(MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY), + typeMapping.getAttributeMappings(MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) + ); + } + + + // **************** maps id mappings ************************************** + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdMappings(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>(this.getAllSingleRelationshipMappings(typeMapping)) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + protected Iterable<SingleRelationshipMapping2_0> getMapsIdMappingsDefinedLocally(TypeMapping typeMapping) { + return new FilteringIterable<SingleRelationshipMapping2_0>(this.getSingleRelationshipMappings(typeMapping)) { + @Override + protected boolean accept(SingleRelationshipMapping2_0 o) { + return o.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy(); + } + }; + } + + + // **************** misc ************************************************** + + /** + * Return whether an id class is required for this class + */ + protected boolean idClassIsRequired() { + // An id class is required if + // - there are multiple "simple" primary key mappings + // - or there is at least one "complex" primary key mapping + // A simple primary key mapping can be + // - an id mapping + // - a derived id relationship mapping to an entity with a simple primary key + // A complex primary key mapping can be + // - a derived id relationship mapping to an entity with a complex primary key + int simplePrimaryKeyMappingCount = + CollectionTools.size(getIdMappings(typeMapping())); + if (simplePrimaryKeyMappingCount > 1) { + return true; + } + for (SingleRelationshipMapping2_0 relationshipMapping : getDerivedIdMappings(typeMapping())) { + Entity entity = relationshipMapping.getResolvedTargetEntity(); + if (entity != null) { + if (definesComplexPrimaryKey(entity)) { + return true; + } + else { + simplePrimaryKeyMappingCount++; + } + if (simplePrimaryKeyMappingCount > 1) { + return true; + } + } + } + return false; + } + + protected boolean hasDerivedIdMappingMatchingIdClass(JavaPersistentType idClass) { + for (SingleRelationshipMapping2_0 each : getDerivedIdMappings(typeMapping())) { + String primaryKeyTypeName = getTargetEntityPrimaryKeyTypeName(each); + if (idClass.getName().equals(primaryKeyTypeName)) { + return true; + } + } + return false; + } + + protected String getTargetEntityPrimaryKeyTypeName(SingleRelationshipMapping2_0 relationshipMapping) { + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity != null) { + return getPrimaryKeyTypeName(targetEntity); + } + return null; + } + + protected String getTypeNameForIdClass(AttributeMapping attributeMapping) { + String mappingKey = attributeMapping.getKey(); + if (CollectionTools.contains(this.getIdMappingKeys(), mappingKey)) { + return attributeMapping.getPersistentAttribute().getTypeName(); + } + if (CollectionTools.contains(this.getSingleRelationshipMappingKeys(), mappingKey)) { + SingleRelationshipMapping2_0 relationshipMapping = (SingleRelationshipMapping2_0) attributeMapping; + Entity targetEntity = relationshipMapping.getResolvedTargetEntity(); + if (targetEntity != null) { + return getPrimaryKeyTypeName(targetEntity); + } + } + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTableValidator.java new file mode 100644 index 0000000000..18b0a273bd --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTableValidator.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractTableValidator + implements JptValidator +{ + + protected final PersistentAttribute persistentAttribute; + + protected final Table table; + + protected final TableTextRangeResolver textRangeResolver; + + protected AbstractTableValidator( + Table table, + TableTextRangeResolver textRangeResolver) { + this(null, table, textRangeResolver); + } + + protected AbstractTableValidator( + PersistentAttribute persistentAttribute, + Table table, + TableTextRangeResolver textRangeResolver) { + super(); + this.persistentAttribute = persistentAttribute; + this.table = table; + this.textRangeResolver = textRangeResolver; + } + + protected Table getTable() { + return this.table; + } + + protected TableTextRangeResolver getTextRangeResolver() { + return this.textRangeResolver; + } + + protected boolean isPersistentAttributeVirtual() { + return this.persistentAttribute != null && this.persistentAttribute.isVirtual(); + } + + protected String getPersistentAttributeName() { + return this.persistentAttribute.getName(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + if (this.validatesAgainstDatabase()) { + return this.validateAgainstDatabase(messages); + } + return false; + } + + protected boolean validatesAgainstDatabase() { + return this.table.validatesAgainstDatabase(); + } + + protected boolean validateAgainstDatabase(List<IMessage> messages) { + if ( ! this.table.catalogIsResolved()) { + messages.add(buildUnresolvedCatalogMessage()); + return false; + } + + if ( ! this.table.schemaIsResolved()) { + messages.add(buildUnresolvedSchemaMessage()); + return false; + } + + if ( ! this.table.isResolved()) { + if (this.table.getName() != null) { //if name is null, the validation will be handled elsewhere, such as the target entity is not defined + messages.add(buildUnresolvedNameMessage()); + } + return false; + } + return true; + } + + protected IMessage buildUnresolvedCatalogMessage() { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualAttributeUnresolvedCatalogMessage(); + } + return this.buildUnresolvedCatalogMessage(this.getUnresolvedCatalogMessage()); + } + + protected abstract String getUnresolvedCatalogMessage(); + + protected IMessage buildUnresolvedCatalogMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] {this.table.getCatalog(), this.table.getName()}, + this.table, + this.textRangeResolver.getCatalogTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnresolvedCatalogMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedCatalogMessage(), + new String[] {this.getPersistentAttributeName(), this.table.getCatalog(), this.table.getName()}, + this.table, + this.textRangeResolver.getCatalogTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedCatalogMessage(); + + protected IMessage buildUnresolvedSchemaMessage() { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualAttributeUnresolvedSchemaMessage(); + } + return this.buildUnresolvedSchemaMessage(this.getUnresolvedSchemaMessage()); + } + + protected abstract String getUnresolvedSchemaMessage(); + + protected IMessage buildUnresolvedSchemaMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] {this.table.getSchema(), this.table.getName()}, + this.table, + this.textRangeResolver.getSchemaTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnresolvedSchemaMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedSchemaMessage(), + new String[] {this.getPersistentAttributeName(), this.table.getSchema(), this.table.getName()}, + this.table, + this.textRangeResolver.getSchemaTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedSchemaMessage(); + + protected IMessage buildUnresolvedNameMessage() { + if (isPersistentAttributeVirtual()) { + return this.buildVirtualAttributeUnresolvedNameMessage(); + } + return this.buildUnresolvedNameMessage(this.getUnresolvedNameMessage()); + } + + protected abstract String getUnresolvedNameMessage(); + + protected IMessage buildUnresolvedNameMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] {this.table.getName()}, + this.table, + this.textRangeResolver.getNameTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] {this.getPersistentAttributeName(), this.table.getName()}, + this.table, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedNameMessage(); + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTypeMappingValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTypeMappingValidator.java new file mode 100644 index 0000000000..88498168b8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AbstractTypeMappingValidator.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +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.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class AbstractTypeMappingValidator<T extends TypeMapping> + implements JptValidator +{ + protected T typeMapping; + + protected JavaResourcePersistentType jrpt; + + protected TypeMappingTextRangeResolver textRangeResolver; + + + protected AbstractTypeMappingValidator( + T typeMapping, JavaResourcePersistentType jrpt, TypeMappingTextRangeResolver textRangeResolver) { + this.typeMapping = typeMapping; + this.jrpt = jrpt; + this.textRangeResolver = textRangeResolver; + } + + + public boolean validate(List<IMessage> messages, IReporter reporter) { + this.validateType(messages); + return true; + } + + protected abstract void validateType(List<IMessage> messages); + + protected boolean isMemberType() { + if (this.jrpt == null) { + return false; + } + return this.jrpt.isMemberType(); + } + + protected boolean isStaticType() { + if (this.jrpt == null) { + return false; + } + return this.jrpt.isStatic(); + } + + protected boolean isFinalType() { + if (this.jrpt == null) { + return false; + } + return this.jrpt.isFinal(); + } + + protected boolean hasPrivateNoArgConstructor() { + if (this.jrpt == null) { + return false; + } + return this.jrpt.hasPrivateNoArgConstructor(); + } + + protected boolean hasNoArgConstructor() { + if (this.jrpt == null) { + return false; + } + return this.jrpt.hasNoArgConstructor(); + } + + protected IMessage buildTypeMessage(String msgID) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + msgID, + new String[] {this.typeMapping.getName()}, + this.typeMapping, + this.textRangeResolver.getTypeMappingTextRange() + ); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java new file mode 100644 index 0000000000..1a154b80b6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideInverseJoinColumnValidator.java @@ -0,0 +1,267 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class AssociationOverrideInverseJoinColumnValidator + extends InverseJoinColumnValidator +{ + final AssociationOverride override; + + public AssociationOverrideInverseJoinColumnValidator( + AssociationOverride override, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, joinColumnOwner, textRangeResolver, provider); + this.override = override; + } + + public AssociationOverrideInverseJoinColumnValidator( + PersistentAttribute persistentAttribute, + AssociationOverride override, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, joinColumnOwner, textRangeResolver, provider); + this.override = override; + } + + @Override + protected TableValidator buildTableValidator() { + return new AssociationOverrideInverseJoinColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected IMessage buildUnresolvedNameMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnresolvedNameMessage() : + super.buildUnresolvedNameMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] { + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName()}, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + public IMessage buildUnresolvedReferencedColumnNameMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnresolvedReferencedColumnNameMessage() : + super.buildUnresolvedReferencedColumnNameMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] { + this.override.getName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedReferencedColumnNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS, + new String[] {this.override.getName()}, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS; + } + + @Override + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS, + new String[] {this.override.getName()}, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS; + } + + + public class AssociationOverrideInverseJoinColumnTableValidator + extends InverseJoinColumnTableValidator + { + protected AssociationOverrideInverseJoinColumnTableValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + public IMessage buildTableNotValidMessage() { + return AssociationOverrideInverseJoinColumnValidator.this.override.isVirtual() ? + this.buildVirtualOverrideColumnTableNotValidMessage() : + super.buildTableNotValidMessage(); + } + + protected IMessage buildVirtualOverrideColumnTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualOverrideColumnTableNotValidMessage(), + new String[] { + AssociationOverrideInverseJoinColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + protected String getVirtualOverrideColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected IMessage buildVirtualAttributeTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeColumnTableNotValidMessage(), + new String[] { + this.getPersistentAttributeName(), + AssociationOverrideInverseJoinColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinColumnValidator.java new file mode 100644 index 0000000000..20ee22bc99 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinColumnValidator.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class AssociationOverrideJoinColumnValidator + extends JoinColumnValidator +{ + final AssociationOverride override; + + + public AssociationOverrideJoinColumnValidator( + AssociationOverride override, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, joinColumnOwner, textRangeResolver, provider); + this.override = override; + } + + public AssociationOverrideJoinColumnValidator( + PersistentAttribute persistentAttribute, + AssociationOverride override, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, joinColumnOwner, textRangeResolver, provider); + this.override = override; + } + + @Override + protected TableValidator buildTableValidator() { + return new AssociationOverrideJoinColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected IMessage buildUnresolvedNameMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnresolvedNameMessage() : + super.buildUnresolvedNameMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] { + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + public IMessage buildUnresolvedReferencedColumnNameMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnresolvedReferencedColumnNameMessage() : + super.buildUnresolvedReferencedColumnNameMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] { + this.override.getName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedReferencedColumnNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualOverrideUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.override.getName()}, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return this.override.isVirtual() ? + this.buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualOverrideUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.override.getName()}, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + + public class AssociationOverrideJoinColumnTableValidator + extends JoinColumnTableValidator + { + protected AssociationOverrideJoinColumnTableValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + public IMessage buildTableNotValidMessage() { + return AssociationOverrideJoinColumnValidator.this.override.isVirtual() ? + this.buildVirtualOverrideColumnTableNotValidMessage() : + super.buildTableNotValidMessage(); + } + + protected IMessage buildVirtualOverrideColumnTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualOverrideColumnTableNotValidMessage(), + new String[] { + AssociationOverrideJoinColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + protected String getVirtualOverrideColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected IMessage buildVirtualAttributeTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeColumnTableNotValidMessage(), + new String[] { + this.getPersistentAttributeName(), + AssociationOverrideJoinColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_JOIN_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java new file mode 100644 index 0000000000..c315e08b8f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideJoinTableValidator.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class AssociationOverrideJoinTableValidator extends AbstractJoinTableValidator +{ + private final AssociationOverride override; + + public AssociationOverrideJoinTableValidator( + AssociationOverride override, + JoinTable table, + TableTextRangeResolver textRangeResolver) { + super(table, textRangeResolver); + this.override = override; + } + + public AssociationOverrideJoinTableValidator( + PersistentAttribute persistentAttribute, + AssociationOverride override, + JoinTable table, + TableTextRangeResolver textRangeResolver) { + super(persistentAttribute, table, textRangeResolver); + this.override = override; + } + + @Override + protected IMessage buildUnresolvedNameMessage() { + if (this.override.isVirtual()) { + return this.buildVirtualOverrideUnresolvedNameMessage(); + } + return super.buildUnresolvedNameMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME, + new String[] {this.override.getName(), this.getTable().getName()}, + this.getTable(), + this.getTextRangeResolver().getNameTextRange() + ); + } + + @Override + protected IMessage buildUnresolvedCatalogMessage() { + if (this.override.isVirtual()) { + return this.buildVirtualOverrideUnresolvedCatalogMessage(); + } + return super.buildUnresolvedCatalogMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedCatalogMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG, + new String[] {this.override.getName(), this.getTable().getCatalog()}, + this.getTable(), + this.getTextRangeResolver().getCatalogTextRange() + ); + } + + @Override + protected IMessage buildUnresolvedSchemaMessage() { + if (this.override.isVirtual()) { + return this.buildVirtualOverrideUnresolvedSchemaMessage(); + } + return super.buildUnresolvedSchemaMessage(); + } + + protected IMessage buildVirtualOverrideUnresolvedSchemaMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA, + new String[] {this.override.getName(), this.getTable().getSchema()}, + this.getTable(), + this.getTextRangeResolver().getSchemaTextRange() + ); + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedCatalogMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedSchemaMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } + + @Override + protected String getVirtualAttributeUnresolvedCatalogMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } + + @Override + protected String getVirtualAttributeUnresolvedSchemaMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException("Nested relationship mappings with JoinTable are unsupported"); //$NON-NLS-1$ + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideValidator.java new file mode 100644 index 0000000000..d0d4e0e8ce --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AssociationOverrideValidator.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.AssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class AssociationOverrideValidator + extends OverrideValidator +{ + public AssociationOverrideValidator( + AssociationOverride override, + AssociationOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(override, container, textRangeResolver, overrideDescriptionProvider); + } + + public AssociationOverrideValidator( + PersistentAttribute persistentAttribute, + AssociationOverride override, + AssociationOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(persistentAttribute, override, container, textRangeResolver, overrideDescriptionProvider); + } + + @Override + protected String getVirtualOverrideUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVALID_NAME; + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.ASSOCIATION_OVERRIDE_INVALID_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ASSOCIATION_OVERRIDE_INVALID_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideColumnValidator.java new file mode 100644 index 0000000000..9d4b58d081 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideColumnValidator.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AttributeOverride; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class AttributeOverrideColumnValidator + extends NamedColumnValidator +{ + final AttributeOverride override; + + public AttributeOverrideColumnValidator( + AttributeOverride override, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider message) { + super(column, textRangeResolver, message); + this.override = override; + } + + public AttributeOverrideColumnValidator( + PersistentAttribute persistentAttribute, + AttributeOverride override, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider message) { + super(persistentAttribute, column, textRangeResolver, message); + this.override = override; + } + + @Override + protected TableValidator buildTableValidator() { + return new AttributeOverrideColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected IMessage buildUnresolvedNameMessage() { + return this.override.isVirtual() ? + this.buildVirtualColumnUnresolvedNameMessage() : + super.buildUnresolvedNameMessage(); + } + + protected IMessage buildVirtualColumnUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualOverrideUnresolvedNameMessage(), + new String[] { + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + protected String getVirtualOverrideUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME; + } + + + public class AttributeOverrideColumnTableValidator + extends BaseColumnTableValidator + { + protected AttributeOverrideColumnTableValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + public IMessage buildTableNotValidMessage() { + return AttributeOverrideColumnValidator.this.override.isVirtual() ? + this.buildVirtualOverrideColumnTableNotValidMessage() : + super.buildTableNotValidMessage(); + } + + protected IMessage buildVirtualOverrideColumnTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualOverrideColumnTableNotValidMessage(), + new String[] { + AttributeOverrideColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + protected String getVirtualOverrideColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected IMessage buildVirtualAttributeTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeColumnTableNotValidMessage(), + new String[] { + this.getPersistentAttributeName(), + AttributeOverrideColumnValidator.this.override.getName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideValidator.java new file mode 100644 index 0000000000..4cc07bea91 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/AttributeOverrideValidator.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AttributeOverride; +import org.eclipse.jpt.jpa.core.context.AttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class AttributeOverrideValidator + extends OverrideValidator +{ + public AttributeOverrideValidator( + AttributeOverride override, + AttributeOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(override, container, textRangeResolver, overrideDescriptionProvider); + } + + public AttributeOverrideValidator( + PersistentAttribute persistentAttribute, + AttributeOverride override, + AttributeOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(persistentAttribute, override, container, textRangeResolver, overrideDescriptionProvider); + } + + @Override + protected String getVirtualOverrideUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_OVERRIDE_INVALID_NAME; + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.ATTRIBUTE_OVERRIDE_INVALID_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_INVALID_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseColumnTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseColumnTableValidator.java new file mode 100644 index 0000000000..e05ac5aa80 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseColumnTableValidator.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.AbstractNamedColumnValidator.TableValidator; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class BaseColumnTableValidator + implements TableValidator +{ + protected final PersistentAttribute persistentAttribute; + + protected final BaseColumn column; + + protected final BaseColumnTextRangeResolver textRangeResolver; + + protected final TableDescriptionProvider tableDescriptionProvider; + + + protected BaseColumnTableValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider tableDescriptionProvider) { + super(); + this.persistentAttribute = persistentAttribute; + this.column = column; + this.textRangeResolver = textRangeResolver; + this.tableDescriptionProvider = tableDescriptionProvider; + } + + protected boolean isPersistentAttributeVirtual() { + return (this.persistentAttribute != null) && this.persistentAttribute.isVirtual(); + } + + protected String getPersistentAttributeName() { + return this.persistentAttribute.getName(); + } + + public boolean tableNameIsInvalid() { + return this.column.tableNameIsInvalid(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + messages.add(this.buildTableNotValidMessage()); + return false; + } + + public IMessage buildTableNotValidMessage() { + if (this.isPersistentAttributeVirtual()) { + return this.buildVirtualAttributeTableNotValidMessage(); + } + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getColumnTableNotValidMessage(), + new String[] { + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + protected String getColumnTableNotValidMessage() { + return JpaValidationMessages.COLUMN_TABLE_NOT_VALID; + } + + protected String getColumnTableDescriptionMessage() { + return this.tableDescriptionProvider.getColumnTableDescriptionMessage(); + } + + protected IMessage buildVirtualAttributeTableNotValidMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeColumnTableNotValidMessage(), + new String[] { + this.getPersistentAttributeName(), + this.column.getTable(), + this.column.getName(), + this.getColumnTableDescriptionMessage() + }, + this.column, + this.textRangeResolver.getTableTextRange() + ); + } + + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLUMN_TABLE_NOT_VALID; + } + + public static interface TableDescriptionProvider { + String getColumnTableDescriptionMessage(); + } + + public static class NullTableDescriptionProvider implements TableDescriptionProvider { + public String getColumnTableDescriptionMessage() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseJoinColumnValidator.java new file mode 100644 index 0000000000..8867a28110 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/BaseJoinColumnValidator.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.jpa.core.context.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public abstract class BaseJoinColumnValidator<C extends BaseJoinColumn, R extends BaseJoinColumnTextRangeResolver> + extends AbstractNamedColumnValidator<C, R> +{ + private final BaseJoinColumn.Owner joinColumnOwner; + + protected BaseJoinColumnValidator( + C column, + BaseJoinColumn.Owner joinColumnOwner, + R textRangeResolver, + TableDescriptionProvider provider) { + super(column, textRangeResolver, provider); + this.joinColumnOwner = joinColumnOwner; + } + + protected BaseJoinColumnValidator( + PersistentAttribute persistentAttribute, + C column, + BaseJoinColumn.Owner joinColumnOwner, + R textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + this.joinColumnOwner = joinColumnOwner; + } + + @Override + //this method will only be called if the table validates correctly + protected void validateName(List<IMessage> messages) { + this.validateJoinColumnName(messages); + this.validateReferencedColumnName(messages); + } + + protected void validateJoinColumnName(List<IMessage> messages) { + if ((this.column.getSpecifiedName() == null) && (this.joinColumnOwner.joinColumnsSize() > 1)) { + messages.add(this.buildUnspecifiedNameMultipleJoinColumnsMessage()); + } + else if (this.column.getName() != null){ + super.validateName(messages); + } + //If the name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected void validateReferencedColumnName(List<IMessage> messages) { + if ((this.column.getSpecifiedReferencedColumnName() == null) && (this.joinColumnOwner.joinColumnsSize() > 1)) { + messages.add(this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage()); + } + //bug 315292 is the reason we are only validating if there is a specified referenced column name + else if (this.column.getSpecifiedReferencedColumnName() != null) { + if ((this.column.getReferencedColumnDbTable() != null) && ! this.column.referencedColumnIsResolved()) { + messages.add(this.buildUnresolvedReferencedColumnNameMessage()); + } + } + //If the referenced column name is null and there is only one join-column, one of these validation messages will apply + // 1. target entity does not have a primary key + // 2. target entity is not specified + // 3. target entity is not an entity + } + + protected IMessage buildUnresolvedReferencedColumnNameMessage() { + return this.isPersistentAttributeVirtual() ? + this.buildVirtualAttributeUnresolvedReferencedColumnNameMessage() : + this.buildUnresolvedReferencedColumnNameMessage(this.getUnresolvedReferencedColumnNameMessage()); + } + + protected abstract String getUnresolvedReferencedColumnNameMessage(); + + protected IMessage buildUnresolvedReferencedColumnNameMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] { + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedReferencedColumnNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedReferencedColumnNameMessage(); + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return this.isPersistentAttributeVirtual() ? + this.buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() : + this.buildUnspecifiedNameMultipleJoinColumnsMessage(this.getUnspecifiedNameMultipleJoinColumnsMessage()); + } + + protected abstract String getUnspecifiedNameMultipleJoinColumnsMessage(); + + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + StringTools.EMPTY_STRING_ARRAY, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(), + new String[] {this.getPersistentAttributeName()}, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage(); + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return this.isPersistentAttributeVirtual() ? + this.buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() : + this.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(this.getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage()); + } + + protected abstract String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + StringTools.EMPTY_STRING_ARRAY, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + protected IMessage buildVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(), + new String[] {this.getPersistentAttributeName()}, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/CollectionTableTableDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/CollectionTableTableDescriptionProvider.java new file mode 100644 index 0000000000..3a771f49a2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/CollectionTableTableDescriptionProvider.java @@ -0,0 +1,12 @@ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages; + +public class CollectionTableTableDescriptionProvider implements TableDescriptionProvider +{ + public String getColumnTableDescriptionMessage() { + return JpaValidationDescriptionMessages.DOES_NOT_MATCH_COLLECTION_TABLE; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/DiscriminatorColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/DiscriminatorColumnValidator.java new file mode 100644 index 0000000000..28b4c7c6f0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/DiscriminatorColumnValidator.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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class DiscriminatorColumnValidator + extends AbstractNamedColumnValidator<NamedColumn, NamedColumnTextRangeResolver> +{ + public DiscriminatorColumnValidator( + NamedColumn namedColumn, + NamedColumnTextRangeResolver textRangeResolver) { + super(namedColumn, textRangeResolver); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.DISCRIMINATOR_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EmbeddableOverrideDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EmbeddableOverrideDescriptionProvider.java new file mode 100644 index 0000000000..615e1c2ed0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EmbeddableOverrideDescriptionProvider.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.internal.jpa1.context.OverrideValidator.OverrideDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages; + +public class EmbeddableOverrideDescriptionProvider implements OverrideDescriptionProvider +{ + public String getOverrideDescriptionMessage() { + return JpaValidationDescriptionMessages.ON_EMBEDDABLE; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityPrimaryKeyJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityPrimaryKeyJoinColumnValidator.java new file mode 100644 index 0000000000..a0d355339e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityPrimaryKeyJoinColumnValidator.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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver; + +public class EntityPrimaryKeyJoinColumnValidator + extends PrimaryKeyJoinColumnValidator +{ + public EntityPrimaryKeyJoinColumnValidator( + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(column, owner, textRangeResolver); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException(); + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + throw new UnsupportedOperationException(); + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + throw new UnsupportedOperationException(); + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + throw new UnsupportedOperationException(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityTableDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityTableDescriptionProvider.java new file mode 100644 index 0000000000..9b77915c89 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/EntityTableDescriptionProvider.java @@ -0,0 +1,12 @@ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages; + +public class EntityTableDescriptionProvider implements TableDescriptionProvider +{ + public String getColumnTableDescriptionMessage() { + return JpaValidationDescriptionMessages.NOT_VALID_FOR_THIS_ENTITY; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.java new file mode 100644 index 0000000000..8ce6e54411 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericEntityPrimaryKeyValidator.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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver; + +public class GenericEntityPrimaryKeyValidator + extends AbstractEntityPrimaryKeyValidator +{ + public GenericEntityPrimaryKeyValidator(Entity entity, PrimaryKeyTextRangeResolver textRangeResolver) { + super(entity, textRangeResolver); + } + + @Override + protected boolean idClassIsRequired() { + //Short circuit check for idClassIsRequired if any part of the primary key is defined + //in a superclass for Generic types. Other validation will exist and needs to be + //addressed first + if(definesPrimaryKeyOnAncestor(typeMapping())){ + return false; + } + return super.idClassIsRequired(); + } + +}
\ No newline at end of file diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java new file mode 100644 index 0000000000..b500925d93 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericMappedSuperclassPrimaryKeyValidator.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2010 Oracle. + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Oracle - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.MappedSuperclass; +import org.eclipse.jpt.jpa.core.internal.context.PrimaryKeyTextRangeResolver; + +public class GenericMappedSuperclassPrimaryKeyValidator extends + AbstractMappedSuperclassPrimaryKeyValidator { + + public GenericMappedSuperclassPrimaryKeyValidator(MappedSuperclass mappedSuperclass, PrimaryKeyTextRangeResolver textRangeResolver) { + super(mappedSuperclass, textRangeResolver); + } + + @Override + protected boolean idClassIsRequired() { + //Short circuit check for idClassIsRequired if any part of the primary key is defined + //in a superclass for Generic types. Other validation will exist and needs to be + //addressed first + if(definesPrimaryKeyOnAncestor(typeMapping())){ + return false; + } + return super.idClassIsRequired(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericPersistentAttributeValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericPersistentAttributeValidator.java new file mode 100644 index 0000000000..8cee29d41a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericPersistentAttributeValidator.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.PersistentAttributeTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class GenericPersistentAttributeValidator + extends AbstractPersistentAttributeValidator +{ + public GenericPersistentAttributeValidator( + PersistentAttribute persistentAttribute, JavaPersistentAttribute javaPersistentAttribute, PersistentAttributeTextRangeResolver textRangeResolver) + { + super(persistentAttribute, javaPersistentAttribute, textRangeResolver); + } + + @Override + protected void validateAttribute(List<IMessage> messages) { + if (this.persistentAttribute.getMappingKey() == MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY) { + return; + } + + if (this.isFieldAttribute()) { + if (this.isFinalAttribute()) { + messages.add(this.buildAttributeMessage(JpaValidationMessages.PERSISTENT_ATTRIBUTE_FINAL_FIELD)); + } + if (this.isPublicAttribute()) { + messages.add(this.buildAttributeMessage(JpaValidationMessages.PERSISTENT_ATTRIBUTE_PUBLIC_FIELD)); + } + } + else if (this.isPropertyAttribute()) { + //TODO need to check both the getter and the setter + if (this.isFinalAttribute()) { + messages.add(this.buildAttributeMessage(JpaValidationMessages.PERSISTENT_ATTRIBUTE_FINAL_GETTER)); + } + } + } + + protected IMessage buildAttributeMessage(String msgID) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + msgID, + new String[] {this.persistentAttribute.getName()}, + this.persistentAttribute, + this.textRangeResolver.getAttributeTextRange() + ); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericRootContextNode.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericRootContextNode.java new file mode 100644 index 0000000000..cee97f3904 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericRootContextNode.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.HashBag; +import org.eclipse.jpt.jpa.core.JpaProject; +import org.eclipse.jpt.jpa.core.JptJpaCorePlugin; +import org.eclipse.jpt.jpa.core.context.MappingFileRoot; +import org.eclipse.jpt.jpa.core.context.persistence.Persistence; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceXml; +import org.eclipse.jpt.jpa.core.internal.context.AbstractJpaContextNode; +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.JpaRootContextNode2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.persistence.PersistenceXml2_0; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourceCompilationUnit; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.jpa.core.resource.xml.JpaXmlResource; +import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * the context model root + */ +public class GenericRootContextNode + extends AbstractJpaContextNode + implements JpaRootContextNode2_0 +{ + /* This object has no parent, so it must point to the JPA project explicitly. */ + protected final JpaProject jpaProject; + + /* Main context object. */ + protected PersistenceXml persistenceXml; + + + public GenericRootContextNode(JpaProject jpaProject) { + super(null); // the JPA project is not really a "parent"... + + if (jpaProject == null) { + throw new NullPointerException(); + } + this.jpaProject = jpaProject; + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncPersistenceXml(); + } + + @Override + public void update() { + super.update(); + this.updatePersistenceXml(); + } + + + // ********** persistence.xml ********** + + public PersistenceXml getPersistenceXml() { + return this.persistenceXml; + } + + protected void setPersistenceXml(PersistenceXml persistenceXml) { + PersistenceXml old = this.persistenceXml; + this.persistenceXml = persistenceXml; + this.firePropertyChanged(PERSISTENCE_XML_PROPERTY, old, persistenceXml); + } + + protected void syncPersistenceXml() { + if (this.persistenceXml != null) { + this.persistenceXml.synchronizeWithResourceModel(); + } + } + + /** + * Check whether the XML resource has either appeared or disappeared. + * If it is still present, it will be the same instance. + */ + protected void updatePersistenceXml() { + JpaXmlResource xmlResource = this.resolvePersistenceXmlResource(); + if (xmlResource == null) { + if (this.persistenceXml != null) { + this.persistenceXml.dispose(); + this.setPersistenceXml(null); + } + } else { + if (this.persistenceXml == null) { + this.setPersistenceXml(this.buildPersistenceXml(xmlResource)); + } else { + this.persistenceXml.update(); + } + } + } + + protected JpaXmlResource resolvePersistenceXmlResource() { + JpaXmlResource xmlResource = this.jpaProject.getPersistenceXmlResource(); + if (xmlResource == null) { + return null; + } + if (xmlResource.isReverting()) { + // 308254 - this can happen when persistence.xml is closed without saving; + // the model is completely whacked in another thread - so wipe our model(?) + return null; + } + JptResourceType resourceType = xmlResource.getResourceType(); + if (resourceType == null) { + return null; + } + if ( ! this.getJpaPlatform().supportsResourceType(resourceType)) { + return null; + } + return xmlResource; + } + + protected PersistenceXml buildPersistenceXml(JpaXmlResource xmlResource) { + return this.getJpaFactory().buildPersistenceXml(this, xmlResource); + } + + + // ********** misc ********** + + @Override + protected boolean requiresParent() { + return false; + } + + @Override + public void stateChanged() { + super.stateChanged(); + // forward to JPA project + this.jpaProject.stateChanged(); + } + + @Override + public JpaProject getJpaProject() { + return this.jpaProject; + } + + @Override + public IResource getResource() { + return this.getProject(); + } + + protected IProject getProject() { + return this.jpaProject.getProject(); + } + + @Override + public PersistenceUnit getPersistenceUnit() { + return null; + } + + @Override + public MappingFileRoot getMappingFileRoot() { + return null; + } + + + // ********** metamodel ********** + + public void initializeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + if (this.persistenceXml != null) { + ((PersistenceXml2_0) this.persistenceXml).disposeMetamodel(); + } + } + + + // ********** validation ********** + + public void validate(List<IMessage> messages, IReporter reporter) { + if (reporter.isCancelled()) { + throw new ValidationCancelledException(); + } + + if (this.persistenceXml == null) { + messages.add(buildPersistenceXmlValidationMessage()); + return; + } + if ( ! this.jpaProject.discoversAnnotatedClasses()) { + this.validateOrphanClasses(messages); + } + this.persistenceXml.validate(messages, reporter); + } + + protected IMessage buildPersistenceXmlValidationMessage() { + int severity = IMessage.HIGH_SEVERITY; + IFile file = getPlatformFile(); + if (file != null && file.exists()) { + JpaXmlResource xmlResource = this.jpaProject.getPersistenceXmlResource(); + if (xmlResource != null + && ! getJpaPlatform().supportsResourceType(xmlResource.getResourceType())) { + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PERSISTENCE_XML_UNSUPPORTED_CONTENT, + file); + } + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PERSISTENCE_XML_INVALID_CONTENT, + file); + } + return DefaultJpaValidationMessages.buildMessage( + severity, + JpaValidationMessages.PROJECT_NO_PERSISTENCE_XML, + this); + } + + protected IFile getPlatformFile() { + return this.jpaProject.getPlatformFile(JptJpaCorePlugin.DEFAULT_PERSISTENCE_XML_RUNTIME_PATH); + } + + protected void validateOrphanClasses(List<IMessage> messages) { + Persistence persistence = this.persistenceXml.getPersistence(); + if (persistence == null) { + return; // handled with other validation + } + if (persistence.persistenceUnitsSize() != 1) { + return; // the context model currently only supports 1 persistence unit + } + + PersistenceUnit persistenceUnit = persistence.persistenceUnits().next(); + HashBag<String> annotatedClassNames = CollectionTools.bag(this.jpaProject.annotatedJavaSourceClassNames()); + HashBag<String> orphans = annotatedClassNames.clone(); + for (String annotatedClassName : annotatedClassNames) { + if (persistenceUnit.specifiesPersistentType(annotatedClassName)) { + orphans.remove(annotatedClassName); + } + } + + // TODO remove 'jrcu' + // replace jrcu.getFile() with jrpt.getFile() + // replace jrpt.getMappingAnnotation().getTextRange(jrcu.buildASTRoot()) + // with jrpt.getMappingAnnotation().getTextRange() + // (new method #getTextRange() ?) + for (String orphan : orphans) { + JavaResourcePersistentType jrpt = this.jpaProject.getJavaResourcePersistentType(orphan); + JavaResourceCompilationUnit jrcu = jrpt.getJavaResourceCompilationUnit(); + if (jrpt.isMapped()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_MAPPED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT, + new String[] {jrpt.getQualifiedName()}, + jrpt.getFile(), + jrpt.getNameTextRange(jrcu.buildASTRoot()) + ) + ); + } + else { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_ANNOTATED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT, + new String[] {jrpt.getName()}, + jrpt.getFile(), + jrpt.getNameTextRange(jrcu.buildASTRoot()) + ) + ); + } + } + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericTypeMappingValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericTypeMappingValidator.java new file mode 100644 index 0000000000..6a2ab46d5d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/GenericTypeMappingValidator.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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class GenericTypeMappingValidator + extends AbstractTypeMappingValidator<TypeMapping> +{ + public GenericTypeMappingValidator(TypeMapping typeMapping, JavaResourcePersistentType jrpt, TypeMappingTextRangeResolver textRangeResolver) { + super(typeMapping, jrpt, textRangeResolver); + } + + @Override + protected void validateType(List<IMessage> messages) { + if (this.isFinalType()) { + messages.add(this.buildTypeMessage(JpaValidationMessages.TYPE_MAPPING_FINAL_CLASS)); + } + if (this.isMemberType()) { + messages.add(this.buildTypeMessage(JpaValidationMessages.TYPE_MAPPING_MEMBER_CLASS)); + } + if (this.hasNoArgConstructor()) { + if (this.hasPrivateNoArgConstructor()) { + messages.add(this.buildTypeMessage(JpaValidationMessages.TYPE_MAPPING_CLASS_PRIVATE_NO_ARG_CONSTRUCTOR)); + } + } + else { + messages.add(this.buildTypeMessage(JpaValidationMessages.TYPE_MAPPING_CLASS_MISSING_NO_ARG_CONSTRUCTOR)); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/InverseJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/InverseJoinColumnValidator.java new file mode 100644 index 0000000000..bad52f726d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/InverseJoinColumnValidator.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class InverseJoinColumnValidator + extends BaseJoinColumnValidator<JoinColumn, JoinColumnTextRangeResolver> +{ + public InverseJoinColumnValidator( + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, joinColumnOwner, textRangeResolver, provider); + } + + public InverseJoinColumnValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, joinColumnOwner, textRangeResolver, provider); + } + + @Override + protected TableValidator buildTableValidator() { + return new InverseJoinColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + public static class InverseJoinColumnTableValidator + extends BaseColumnTableValidator + { + public InverseJoinColumnTableValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected String getColumnTableNotValidMessage() { + return JpaValidationMessages.INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinColumnValidator.java new file mode 100644 index 0000000000..9fa255dafb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinColumnValidator.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.JoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class JoinColumnValidator + extends BaseJoinColumnValidator<JoinColumn, JoinColumnTextRangeResolver> +{ + public JoinColumnValidator( + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, joinColumnOwner, textRangeResolver, provider); + } + + public JoinColumnValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumn.Owner joinColumnOwner, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, joinColumnOwner, textRangeResolver, provider); + } + + @Override + protected TableValidator buildTableValidator() { + return new JoinColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + public static class JoinColumnTableValidator + extends BaseColumnTableValidator + { + public JoinColumnTableValidator( + PersistentAttribute persistentAttribute, + JoinColumn column, + JoinColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected String getColumnTableNotValidMessage() { + return JpaValidationMessages.JOIN_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableTableDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableTableDescriptionProvider.java new file mode 100644 index 0000000000..d2b27a49f7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableTableDescriptionProvider.java @@ -0,0 +1,12 @@ +package org.eclipse.jpt.jpa.core.internal.jpa1.context; + +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages; + +public class JoinTableTableDescriptionProvider implements TableDescriptionProvider +{ + public String getColumnTableDescriptionMessage() { + return JpaValidationDescriptionMessages.DOES_NOT_MATCH_JOIN_TABLE; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableValidator.java new file mode 100644 index 0000000000..352204fe2a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/JoinTableValidator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class JoinTableValidator extends AbstractJoinTableValidator +{ + public JoinTableValidator(JoinTable table, TableTextRangeResolver textRangeResolver) { + super(table, textRangeResolver); + } + + public JoinTableValidator(PersistentAttribute persistentAttribute, JoinTable table, TableTextRangeResolver textRangeResolver) { + super(persistentAttribute, table, textRangeResolver); + } + + @Override + protected String getVirtualAttributeUnresolvedCatalogMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getVirtualAttributeUnresolvedSchemaMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideColumnValidator.java new file mode 100644 index 0000000000..34ddf7ba46 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideColumnValidator.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AttributeOverride; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class MapKeyAttributeOverrideColumnValidator + extends AttributeOverrideColumnValidator +{ + public MapKeyAttributeOverrideColumnValidator( + AttributeOverride override, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(override, column, textRangeResolver, provider); + } + + public MapKeyAttributeOverrideColumnValidator( + PersistentAttribute persistentAttribute, + AttributeOverride override, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, override, column, textRangeResolver, provider); + } + + @Override + protected TableValidator buildTableValidator() { + return new MapKeyAttributeOverrideColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected String getVirtualOverrideUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_UNRESOLVED_NAME; + } + + + public class MapKeyAttributeOverrideColumnTableValidator + extends AttributeOverrideColumnTableValidator + { + protected MapKeyAttributeOverrideColumnTableValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected String getVirtualOverrideColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideValidator.java new file mode 100644 index 0000000000..9f6b16d93e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyAttributeOverrideValidator.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.AttributeOverride; +import org.eclipse.jpt.jpa.core.context.AttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class MapKeyAttributeOverrideValidator + extends AttributeOverrideValidator +{ + public MapKeyAttributeOverrideValidator( + AttributeOverride override, + AttributeOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(override, container, textRangeResolver, overrideDescriptionProvider); + } + + public MapKeyAttributeOverrideValidator( + PersistentAttribute persistentAttribute, + AttributeOverride override, + AttributeOverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + super(persistentAttribute, override, container, textRangeResolver, overrideDescriptionProvider); + } + + @Override + protected String getVirtualOverrideUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_INVALID_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_INVALID_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyColumnValidator.java new file mode 100644 index 0000000000..ce044fed43 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MapKeyColumnValidator.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class MapKeyColumnValidator + extends AbstractNamedColumnValidator<BaseColumn, BaseColumnTextRangeResolver> +{ + + public MapKeyColumnValidator( + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, textRangeResolver, provider); + } + + public MapKeyColumnValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected TableValidator buildTableValidator() { + return new MapKeyColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.MAP_KEY_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_UNRESOLVED_NAME; + } + + public static class MapKeyColumnTableValidator + extends BaseColumnTableValidator + { + protected MapKeyColumnTableValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected String getColumnTableNotValidMessage() { + return JpaValidationMessages.MAP_KEY_COLUMN_TABLE_NOT_VALID; + } + + @Override + protected String getVirtualAttributeColumnTableNotValidMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID; + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MappedSuperclassOverrideDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MappedSuperclassOverrideDescriptionProvider.java new file mode 100644 index 0000000000..71a7dc083e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/MappedSuperclassOverrideDescriptionProvider.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.internal.jpa1.context.OverrideValidator.OverrideDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages; + +public class MappedSuperclassOverrideDescriptionProvider implements OverrideDescriptionProvider +{ + public String getOverrideDescriptionMessage() { + return JpaValidationDescriptionMessages.ON_MAPPED_SUPERCLASS; + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/NamedColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/NamedColumnValidator.java new file mode 100644 index 0000000000..76a6fd5513 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/NamedColumnValidator.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class NamedColumnValidator + extends AbstractNamedColumnValidator<BaseColumn, BaseColumnTextRangeResolver> +{ + + public NamedColumnValidator( + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(column, textRangeResolver, provider); + } + + public NamedColumnValidator( + PersistentAttribute persistentAttribute, + BaseColumn column, + BaseColumnTextRangeResolver textRangeResolver, + TableDescriptionProvider provider) { + super(persistentAttribute, column, textRangeResolver, provider); + } + + @Override + protected TableValidator buildTableValidator() { + return new BaseColumnTableValidator(this.persistentAttribute, this.column, this.textRangeResolver, this.tableDescriptionProvider); + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLUMN_UNRESOLVED_NAME; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OneToOnePrimaryKeyJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OneToOnePrimaryKeyJoinColumnValidator.java new file mode 100644 index 0000000000..579b90c317 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OneToOnePrimaryKeyJoinColumnValidator.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class OneToOnePrimaryKeyJoinColumnValidator + extends PrimaryKeyJoinColumnValidator +{ + public OneToOnePrimaryKeyJoinColumnValidator( + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(column, owner, textRangeResolver); + } + + public OneToOnePrimaryKeyJoinColumnValidator( + PersistentAttribute persistentAttribute, + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(persistentAttribute, column, owner, textRangeResolver); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_ATTRIBUTE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OverrideValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OverrideValidator.java new file mode 100644 index 0000000000..5e78c6a6ba --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/OverrideValidator.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * 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.jpa1.context; + +import java.util.List; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +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.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public abstract class OverrideValidator + implements JptValidator +{ + protected final PersistentAttribute persistentAttribute; + + protected final Override_ override; + + protected final OverrideContainer container; + + protected final OverrideTextRangeResolver textRangeResolver; + + protected final OverrideDescriptionProvider overrideDescriptionProvider; + + protected OverrideValidator( + Override_ override, + OverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + this(null, override, container, textRangeResolver, overrideDescriptionProvider); + } + + + protected OverrideValidator( + PersistentAttribute persistentAttribute, + Override_ override, + OverrideContainer container, + OverrideTextRangeResolver textRangeResolver, + OverrideDescriptionProvider overrideDescriptionProvider) { + this.persistentAttribute = persistentAttribute; + this.override = override; + this.container = container; + this.textRangeResolver = textRangeResolver; + this.overrideDescriptionProvider = overrideDescriptionProvider; + } + + protected boolean persistentAttributeIsVirtual() { + return (this.persistentAttribute != null) && this.persistentAttribute.isVirtual(); + } + + protected String getPersistentAttributeName() { + return this.persistentAttribute.getName(); + } + + protected String getOverrideDescriptionMessage() { + return this.overrideDescriptionProvider.getOverrideDescriptionMessage(); + } + + public boolean validate(List<IMessage> messages, IReporter reporter) { + return this.validateName(messages); + } + + protected boolean validateName(List<IMessage> messages) { + if ( ! CollectionTools.contains(this.container.allOverridableNames(), this.override.getName())) { + messages.add(this.buildUnresolvedNameMessage()); + return false; + } + return true; + } + + protected IMessage buildUnresolvedNameMessage() { + if (this.override.isVirtual()) { + return this.buildVirtualUnresolvedNameMessage(); + } + if (this.persistentAttributeIsVirtual()) { + return this.buildVirtualAttributeUnresolvedNameMessage(); + } + return this.buildUnresolvedNameMessage(this.getUnresolvedNameMessage()); + } + + protected IMessage buildVirtualUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualOverrideUnresolvedNameMessage(), + new String[] { + this.override.getName(), + this.getOverrideDescriptionMessage(), + this.container.getOverridableTypeMapping().getName() + }, + this.override, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getVirtualOverrideUnresolvedNameMessage(); + + protected IMessage buildUnresolvedNameMessage(String message) { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + message, + new String[] { + this.override.getName(), + this.getOverrideDescriptionMessage(), + this.container.getOverridableTypeMapping().getName() + }, + this.override, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getUnresolvedNameMessage(); + + protected IMessage buildVirtualAttributeUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + this.getVirtualAttributeUnresolvedNameMessage(), + new String[] { + this.getPersistentAttributeName(), + this.override.getName(), + this.getOverrideDescriptionMessage(), + this.container.getOverridableTypeMapping().getName() + }, + this.override, + this.textRangeResolver.getNameTextRange() + ); + } + + protected abstract String getVirtualAttributeUnresolvedNameMessage(); + + public interface OverrideDescriptionProvider { + String getOverrideDescriptionMessage(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/PrimaryKeyJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/PrimaryKeyJoinColumnValidator.java new file mode 100644 index 0000000000..6317b29b16 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/PrimaryKeyJoinColumnValidator.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.PersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.NullTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public abstract class PrimaryKeyJoinColumnValidator + extends BaseJoinColumnValidator<BaseJoinColumn, BaseJoinColumnTextRangeResolver> +{ + protected PrimaryKeyJoinColumnValidator( + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(column, owner, textRangeResolver, new NullTableDescriptionProvider()); + } + + protected PrimaryKeyJoinColumnValidator( + PersistentAttribute persistentAttribute, + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(persistentAttribute, column, owner, textRangeResolver, new NullTableDescriptionProvider()); + } + + @Override + public IMessage buildUnresolvedNameMessage() { + return this.column.isVirtual() ? + this.buildUnresolvedNameMessage(this.getVirtualPKJoinColumnUnresolvedNameMessage()) : + super.buildUnresolvedNameMessage(); + } + + protected String getVirtualPKJoinColumnUnresolvedNameMessage() { + return JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected IMessage buildUnresolvedReferencedColumnNameMessage() { + return this.column.isVirtual() ? + this.buildUnresolvedReferencedColumnNameMessage(this.getVirtualPKJoinColumnUnresolvedReferencedColumnNameMessage()) : + super.buildUnresolvedReferencedColumnNameMessage(); + } + + protected String getVirtualPKJoinColumnUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return this.column.isVirtual() ? + this.buildUnspecifiedNameMultipleJoinColumnsMessage(this.getVirtualPKJoinColumnUnspecifiedNameMultipleJoinColumnsMessage()) : + super.buildUnspecifiedNameMultipleJoinColumnsMessage(); + } + + protected String getVirtualPKJoinColumnUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return this.column.isVirtual() ? + this.buildUnspecifiedNameMultipleJoinColumnsMessage(this.getVirtualPKJoinColumnUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage()) : + super.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + protected String getVirtualPKJoinColumnUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.VIRTUAL_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME; + } + + @Override + protected String getUnresolvedReferencedColumnNameMessage() { + return JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME; + } + + @Override + protected String getUnspecifiedNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } + + @Override + protected String getUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return JpaValidationMessages.PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/RelationshipStrategyTableDescriptionProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/RelationshipStrategyTableDescriptionProvider.java new file mode 100644 index 0000000000..abe27fb5d8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/RelationshipStrategyTableDescriptionProvider.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.RelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.BaseColumnTableValidator.TableDescriptionProvider; + +public class RelationshipStrategyTableDescriptionProvider + implements TableDescriptionProvider +{ + private final RelationshipStrategy relationshipStrategy; + + public RelationshipStrategyTableDescriptionProvider(RelationshipStrategy relationshipStrategy) { + super(); + this.relationshipStrategy = relationshipStrategy; + } + + public String getColumnTableDescriptionMessage() { + return this.relationshipStrategy.getColumnTableNotValidDescription(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java new file mode 100644 index 0000000000..15823d3b42 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTablePrimaryKeyJoinColumnValidator.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.SecondaryTable; +import org.eclipse.jpt.jpa.core.internal.context.BaseJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; + +public class SecondaryTablePrimaryKeyJoinColumnValidator + extends PrimaryKeyJoinColumnValidator +{ + private final SecondaryTable secondaryTable; + + public SecondaryTablePrimaryKeyJoinColumnValidator( + SecondaryTable secondaryTable, + BaseJoinColumn column, + BaseJoinColumn.Owner owner, + BaseJoinColumnTextRangeResolver textRangeResolver) { + super(column, owner, textRangeResolver); + this.secondaryTable = secondaryTable; + } + + protected boolean isSecondaryTableVirtual() { + return this.secondaryTable.isVirtual(); + } + + protected String getSecondaryTableName() { + return this.secondaryTable.getName(); + } + + @Override + public IMessage buildUnresolvedNameMessage() { + return this.isSecondaryTableVirtual() ? + this.buildVirtualSecondaryTableUnresolvedNameMessage() : + super.buildUnresolvedNameMessage(); + } + + protected IMessage buildVirtualSecondaryTableUnresolvedNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME, + new String[] { + this.getSecondaryTableName(), + this.column.getName(), + this.column.getDbTable().getName() + }, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException(); + } + + @Override + public IMessage buildUnresolvedReferencedColumnNameMessage() { + return this.isSecondaryTableVirtual() ? + this.buildVirtualSecondaryTableUnresolvedReferencedColumnNameMessage() : + super.buildUnresolvedReferencedColumnNameMessage(); + } + + protected IMessage buildVirtualSecondaryTableUnresolvedReferencedColumnNameMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME, + new String[] { + this.getSecondaryTableName(), + this.column.getReferencedColumnName(), + this.column.getReferencedColumnDbTable().getName() + }, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnresolvedReferencedColumnNameMessage() { + throw new UnsupportedOperationException(); + } + + @Override + public IMessage buildUnspecifiedNameMultipleJoinColumnsMessage() { + return this.isSecondaryTableVirtual() ? + this.buildVirtualSecondaryTableUnspecifiedNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualSecondaryTableUnspecifiedNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.getSecondaryTableName()}, + this.column, + this.textRangeResolver.getNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedNameMultipleJoinColumnsMessage() { + throw new UnsupportedOperationException(); + } + + @Override + public IMessage buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return this.isSecondaryTableVirtual() ? + this.buildVirtualSecondaryTableUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() : + super.buildUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage(); + } + + protected IMessage buildVirtualSecondaryTableUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + return DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS, + new String[] {this.getSecondaryTableName()}, + this.column, + this.textRangeResolver.getReferencedColumnNameTextRange() + ); + } + + @Override + protected String getVirtualAttributeUnspecifiedReferencedColumnNameMultipleJoinColumnsMessage() { + throw new UnsupportedOperationException(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTableValidator.java new file mode 100644 index 0000000000..03b4df0b81 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/SecondaryTableValidator.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.SecondaryTable; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class SecondaryTableValidator extends AbstractTableValidator +{ + public SecondaryTableValidator(SecondaryTable table, TableTextRangeResolver textRangeResolver) { + super(table, textRangeResolver); + } + + @Override + public SecondaryTable getTable() { + return (SecondaryTable) super.getTable(); + } + + @Override + protected String getUnresolvedCatalogMessage() { + return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getVirtualAttributeUnresolvedCatalogMessage() { + throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$ + } + + @Override + protected String getUnresolvedSchemaMessage() { + return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getVirtualAttributeUnresolvedSchemaMessage() { + throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$ + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.SECONDARY_TABLE_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException("No SecondaryTable annotations exist on attributes"); //$NON-NLS-1$ + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/TableValidator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/TableValidator.java new file mode 100644 index 0000000000..a0dad72ed6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/TableValidator.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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.jpa1.context; + +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; + +public class TableValidator extends AbstractTableValidator +{ + public TableValidator(Table table, TableTextRangeResolver textRangeResolver) { + super(table, textRangeResolver); + } + + @Override + protected String getUnresolvedCatalogMessage() { + return JpaValidationMessages.TABLE_UNRESOLVED_CATALOG; + } + + @Override + protected String getVirtualAttributeUnresolvedCatalogMessage() { + throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$ + } + + @Override + protected String getUnresolvedSchemaMessage() { + return JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA; + } + + @Override + protected String getVirtualAttributeUnresolvedSchemaMessage() { + throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$ + } + + @Override + protected String getUnresolvedNameMessage() { + return JpaValidationMessages.TABLE_UNRESOLVED_NAME; + } + + @Override + protected String getVirtualAttributeUnresolvedNameMessage() { + throw new UnsupportedOperationException("No Table annotations exist on attributes"); //$NON-NLS-1$ + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaConverter.java new file mode 100644 index 0000000000..71d9610828 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaConverter.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaConverter; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.resource.java.Annotation; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; + +public abstract class AbstractJavaConverter + extends AbstractJavaJpaContextNode + implements JavaConverter +{ + protected AbstractJavaConverter(JavaAttributeMapping parent) { + super(parent); + } + + + // ********** misc ********** + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + protected JavaAttributeMapping getAttributeMapping() { + return this.getParent(); + } + + protected JavaResourcePersistentAttribute getResourcePersistentAttribute() { + return this.getAttributeMapping().getResourcePersistentAttribute(); + } + + public Annotation getConverterAnnotation() { + return this.getResourcePersistentAttribute().getAnnotation(this.getAnnotationName()); + } + + public void dispose() { + // NOP + } + + protected abstract String getAnnotationName(); +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaOverrideContainer.java new file mode 100644 index 0000000000..860b447bac --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/AbstractJavaOverrideContainer.java @@ -0,0 +1,587 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.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.CompositeListIterable; +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.SubIterableWrapper; +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.BaseColumn; +import org.eclipse.jpt.jpa.core.context.Override_; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.VirtualOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +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.JavaReadOnlyOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverride; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +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.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.resource.java.Annotation; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.jpt.jpa.core.resource.java.NestableAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.OverrideAnnotation; +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 override container + * <p> + * <strong>NB:</strong> Although not typical, a Java override container can + * correspond to only a subset of the annotations in the Java source code. + * In that case, the index of a specified override must be translated to its + * corresponding annotation's index before we manipulate the annotations. + * <p> + * As of JPA 2.0, the only place we need these translations is for the attribute + * overrides for an embedded collection. If an embedded collection is a + * {@link java.util.Map Map}, the attribute overrides can override the mappings + * for either the map's keys or the map's values. The names of the overrides for + * the map's keys are prefixed with <code>"key."</code> while the overrides + * for the map's values are prefixed with <code>"value."</code>. + * (Just a bit of hack, courtesy of the JPA spec committee.) + */ +public abstract class AbstractJavaOverrideContainer< + O extends JavaOverrideContainer.Owner, + R extends JavaReadOnlyOverride, + S extends JavaOverride, + V extends JavaVirtualOverride, + A extends OverrideAnnotation + > + extends AbstractJavaJpaContextNode + implements JavaOverrideContainer +{ + // this can be null if the container is "read-only" (i.e. a "null" container) + protected final O owner; + + protected final Vector<S> specifiedOverrides = new Vector<S>(); + protected final SpecifiedOverrideContainerAdapter specifiedOverrideContainerAdapter = new SpecifiedOverrideContainerAdapter(); + + protected final Vector<V> virtualOverrides = new Vector<V>(); + protected final VirtualOverrideContainerAdapter virtualOverrideContainerAdapter = new VirtualOverrideContainerAdapter(); + + + protected AbstractJavaOverrideContainer(JavaJpaContextNode parent, O owner) { + super(parent); + this.owner = owner; + this.initializeSpecifiedOverrides(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedOverrides(); + // the virtual overrides do not need a sync + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedOverrides()); + this.updateVirtualOverrides(); + } + + + // ********** overrides ********** + + public ListIterator<R> overrides() { + return this.getOverrides().iterator(); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getOverrides() { + return new CompositeListIterable<R>(this.getReadOnlySpecifiedOverrides(), this.getReadOnlyVirtualOverrides()); + } + + public int overridesSize() { + return this.specifiedOverrides.size() + this.virtualOverrides.size(); + } + + public R getOverrideNamed(String name) { + return this.selectOverrideNamed(this.getOverrides(), name); + } + + + // ********** override conversions ********** + + /** + * <em>Silently</em> add the new virtual override before removing the + * specified override, or the <em>update</em> will discover the missing + * virtual override and add it preemptively. + */ + public V convertOverrideToVirtual(Override_ override) { + if (override.isVirtual()) { + throw new IllegalArgumentException("Override is already virtual: " + override); //$NON-NLS-1$ + } + + @SuppressWarnings("unchecked") + S specifiedOverride = (S) override; + int virtualIndex = this.virtualOverrides.size(); + String overrideName = specifiedOverride.getName(); + V virtualOverride = null; + // make sure the specified override actually overrides something before building the virtual override + if (this.overrideWillBeVirtual(overrideName, specifiedOverride)) { + virtualOverride = this.buildVirtualOverride(overrideName); + this.virtualOverrides.add(virtualIndex, virtualOverride); + } + + this.removeSpecifiedOverride(specifiedOverride); // trigger update + + if (virtualOverride != null) { + this.fireItemAdded(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride); + } + return virtualOverride; + } + + /** + * Return whether the specified override name will be a + * <em>virtual</em> override when the specified specified override is + * removed from the container. The override name must be among the + * valid override names and it must not correspond to any of the + * remaining specified overrides. + */ + protected boolean overrideWillBeVirtual(String overrideName, S specifiedOverrideToBeRemoved) { + return CollectionTools.contains(this.allOverridableNames(), overrideName) && + (this.getSpecifiedOverrideNamed(overrideName, specifiedOverrideToBeRemoved) == null); + } + + /** + * <em>Silently</em> remove the virtual override and add the new specified + * override before naming the specified override, or the <em>update</em> + * will discover the dangling virtual override and remove it preemptively. + */ + public S convertOverrideToSpecified(VirtualOverride override) { + if ( ! override.isVirtual()) { + throw new IllegalArgumentException("Override is already specified: " + override); //$NON-NLS-1$ + } + + @SuppressWarnings("unchecked") + V virtualOverride = (V) override; + int virtualIndex = this.virtualOverrides.indexOf(virtualOverride); + this.virtualOverrides.remove(virtualIndex); + + int specifiedIndex = this.specifiedOverrides.size(); + S specifiedOverride = this.buildSpecifiedOverride(this.buildOverrideAnnotation(specifiedIndex)); + this.specifiedOverrides.add(specifiedIndex, specifiedOverride); + + this.initializeSpecifiedOverride(specifiedOverride, virtualOverride); // trigger update + + this.fireItemRemoved(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride); + this.fireItemAdded(SPECIFIED_OVERRIDES_LIST, specifiedIndex, specifiedOverride); + return specifiedOverride; + } + + protected abstract void initializeSpecifiedOverride(S specifiedOverride, V virtualOverride); + + + // ********** specified overrides ********** + + public ListIterator<S> specifiedOverrides() { + return this.getSpecifiedOverrides().iterator(); + } + + protected ListIterable<S> getSpecifiedOverrides() { + return new LiveCloneListIterable<S>(this.specifiedOverrides); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getReadOnlySpecifiedOverrides() { + // S should always be a subtype of R, but we can't enforce that in the + // class declaration... + return (ListIterable<R>) this.getSpecifiedOverrides(); + } + + public int specifiedOverridesSize() { + return this.specifiedOverrides.size(); + } + + public S getSpecifiedOverride(int index) { + return this.specifiedOverrides.get(index); + } + + public S getSpecifiedOverrideNamed(String name) { + return this.getSpecifiedOverrideNamed(name, null); + } + + @SuppressWarnings("unchecked") + protected S getSpecifiedOverrideNamed(String name, S exclude) { + return (S) this.selectOverrideNamed(this.getReadOnlySpecifiedOverrides(), name, exclude); + } + + protected S addSpecifiedOverride() { + return this.addSpecifiedOverride(this.specifiedOverrides.size()); + } + + protected S addSpecifiedOverride(int index) { + A annotation = this.buildOverrideAnnotation(index); + return this.addSpecifiedOverride_(index, annotation); + } + + @SuppressWarnings("unchecked") + protected A buildOverrideAnnotation(int index) { + int annotationIndex = this.calculateNewAnnotationIndex(index); + return (A) this.getResourcePersistentMember().addAnnotation(annotationIndex, this.getOverrideAnnotationName(), this.getOverrideContainerAnnotationName()); + } + + protected int calculateNewAnnotationIndex(int index) { + // if we are adding to the end of the specified list, + // put the annotation after all the existing annotations + if (index == this.specifiedOverrides.size()) { + return CollectionTools.size(this.getOverrideAnnotations()); + } + + // if we are adding to the front of the specified list, + // put the annotation before of all the existing annotations + if (index == 0) { + return 0; + } + + // if we are adding to the middle of the specified list, + // put the annotation immediately after all the previous override's + // existing annotation + return this.translateToAnnotationIndex(index - 1) + 1; + } + + /** + * pre-condition: override exists at the specified index + */ + protected int translateToAnnotationIndex(int index) { + return CollectionTools.indexOf(this.getOverrideAnnotations(), this.specifiedOverrides.get(index).getOverrideAnnotation()); + } + + protected abstract String getOverrideAnnotationName(); + + protected abstract String getOverrideContainerAnnotationName(); + + protected void removeSpecifiedOverride(S override) { + this.removeSpecifiedOverride(this.specifiedOverrides.indexOf(override)); + } + + protected void removeSpecifiedOverride(int index) { + this.removeOverrideAnnotation(index); + this.removeSpecifiedOverride_(index); + } + + protected void removeOverrideAnnotation(int index) { + int annotationIndex = this.translateToAnnotationIndex(index); + this.getResourcePersistentMember().removeAnnotation(annotationIndex, this.getOverrideAnnotationName(), this.getOverrideContainerAnnotationName()); + } + + protected void removeSpecifiedOverride_(int index) { + this.removeItemFromList(index, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + } + + public void moveSpecifiedOverride(int targetIndex, int sourceIndex) { + this.moveOverrideAnnotation(targetIndex, sourceIndex); + this.moveItemInList(targetIndex, sourceIndex, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + } + + protected void moveOverrideAnnotation(int targetIndex, int sourceIndex) { + int targetAnnotationIndex = this.translateToAnnotationIndex(targetIndex); + int sourceAnnotationIndex = this.translateToAnnotationIndex(sourceIndex); + this.getResourcePersistentMember().moveAnnotation(targetAnnotationIndex, sourceAnnotationIndex, this.getOverrideContainerAnnotationName()); + } + + protected void initializeSpecifiedOverrides() { + for (A annotation : this.getRelevantOverrideAnnotations()) { + this.specifiedOverrides.add(this.buildSpecifiedOverride(annotation)); + } + } + + protected abstract S buildSpecifiedOverride(A overrideAnnotation); + + protected void syncSpecifiedOverrides() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedOverrideContainerAdapter); + } + + protected Iterable<A> getRelevantOverrideAnnotations() { + return new FilteringIterable<A>(this.getOverrideAnnotations()) { + @Override + protected boolean accept(A annotation) { + String overrideName = annotation.getName(); + return (overrideName != null) && AbstractJavaOverrideContainer.this.owner.isRelevant(overrideName); + } + }; + } + + protected Iterable<A> getOverrideAnnotations() { + return new SubIterableWrapper<NestableAnnotation, A>( + CollectionTools.iterable(this.overrideAnnotations()) + ); + } + + protected Iterator<NestableAnnotation> overrideAnnotations() { + return (this.owner == null) ? EmptyIterator.<NestableAnnotation>instance() : this.overrideAnnotations_(); + } + + /** + * pre-condition: {@link #owner} is not <code>null</code> + */ + protected Iterator<NestableAnnotation> overrideAnnotations_() { + return this.getResourcePersistentMember().annotations(this.getOverrideAnnotationName(), this.getOverrideContainerAnnotationName()); + } + + protected void moveSpecifiedOverride_(int index, S override) { + this.moveItemInList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + } + + protected S addSpecifiedOverride_(int index, A overrideAnnotation) { + S override = this.buildSpecifiedOverride(overrideAnnotation); + this.addItemToList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + return override; + } + + protected void removeSpecifiedOverride_(S override) { + this.removeSpecifiedOverride_(this.specifiedOverrides.indexOf(override)); + } + + /** + * specified override container adapter + */ + protected class SpecifiedOverrideContainerAdapter + implements ContextContainerTools.Adapter<S, A> + { + public Iterable<S> getContextElements() { + return AbstractJavaOverrideContainer.this.getSpecifiedOverrides(); + } + public Iterable<A> getResourceElements() { + return AbstractJavaOverrideContainer.this.getRelevantOverrideAnnotations(); + } + @SuppressWarnings("unchecked") + public A getResourceElement(S contextElement) { + return (A) contextElement.getOverrideAnnotation(); + } + public void moveContextElement(int index, S element) { + AbstractJavaOverrideContainer.this.moveSpecifiedOverride_(index, element); + } + public void addContextElement(int index, A resourceElement) { + AbstractJavaOverrideContainer.this.addSpecifiedOverride_(index, resourceElement); + } + public void removeContextElement(S element) { + AbstractJavaOverrideContainer.this.removeSpecifiedOverride_(element); + } + } + + + // ********** virtual overrides ********** + + public ListIterator<V> virtualOverrides() { + return this.getVirtualOverrides().iterator(); + } + + protected ListIterable<V> getVirtualOverrides() { + return new LiveCloneListIterable<V>(this.virtualOverrides); + } + + public int virtualOverridesSize() { + return this.virtualOverrides.size(); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getReadOnlyVirtualOverrides() { + // V should always be a subtype of R, but we can't enforce that in the + // class declaration... + return (ListIterable<R>) this.getVirtualOverrides(); + } + + protected void updateVirtualOverrides() { + ContextContainerTools.update(this.virtualOverrideContainerAdapter); + } + + /** + * Return the overridable names that are not already in the list of + * specified overrides. + */ + protected Iterable<String> getVirtualOverrideNames() { + return CollectionTools.iterable(this.virtualOverrideNames()); + } + + protected Iterator<String> virtualOverrideNames() { + return new FilteringIterator<String>(this.allOverridableNames()) { + @Override + protected boolean accept(String name) { + return AbstractJavaOverrideContainer.this.overrideIsVirtual(name); + } + }; + } + + protected boolean overrideIsVirtual(String name) { + return this.getSpecifiedOverrideNamed(name) == null; + } + + protected void moveVirtualOverride(int index, V override) { + this.moveItemInList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + } + + protected V addVirtualOverride(int index, String name) { + V override = this.buildVirtualOverride(name); + this.addItemToList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + return override; + } + + protected abstract V buildVirtualOverride(String name); + + protected void removeVirtualOverride(V override) { + this.removeItemFromList(override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + } + + /** + * virtual override container adapter + * NB: the context override is matched with a resource override by name + */ + protected class VirtualOverrideContainerAdapter + implements ContextContainerTools.Adapter<V, String> + { + public Iterable<V> getContextElements() { + return AbstractJavaOverrideContainer.this.getVirtualOverrides(); + } + public Iterable<String> getResourceElements() { + return AbstractJavaOverrideContainer.this.getVirtualOverrideNames(); + } + public String getResourceElement(V contextElement) { + return contextElement.getName(); + } + public void moveContextElement(int index, V element) { + AbstractJavaOverrideContainer.this.moveVirtualOverride(index, element); + } + public void addContextElement(int index, String resourceElement) { + AbstractJavaOverrideContainer.this.addVirtualOverride(index, resourceElement); + } + public void removeContextElement(V element) { + AbstractJavaOverrideContainer.this.removeVirtualOverride(element); + } + } + + + // ********** misc ********** + + public TypeMapping getTypeMapping() { + return this.owner.getTypeMapping(); + } + + protected JavaResourcePersistentMember getResourcePersistentMember() { + return this.owner.getResourcePersistentMember(); + } + + public TypeMapping getOverridableTypeMapping() { + return this.owner.getOverridableTypeMapping(); + } + + public Iterator<String> allOverridableNames() { + return (this.owner != null) ? this.owner.allOverridableNames() : EmptyIterator.<String>instance(); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.owner.tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.owner.candidateTableNames(); + } + + public Table resolveDbTable(String tableName) { + return this.owner.resolveDbTable(tableName); + } + + public String getDefaultTableName() { + return this.owner.getDefaultTableName(); + } + + public JptValidator buildValidator(Override_ override, OverrideTextRangeResolver textRangeResolver) { + return this.owner.buildValidator(override, this, textRangeResolver); + } + + public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner columnOwner, BaseColumnTextRangeResolver textRangeResolver) { + return this.owner.buildColumnValidator(override, column, columnOwner, textRangeResolver); + } + + public String getPossiblePrefix() { + return this.owner.getPossiblePrefix(); + } + + public String getWritePrefix() { + return this.owner.getWritePrefix(); + } + + protected R selectOverrideNamed(Iterable<R> overrides, String name) { + return this.selectOverrideNamed(overrides, name, null); + } + + protected R selectOverrideNamed(Iterable<R> overrides, String name, S exclude) { + for (R override : overrides) { + if (override == exclude) { + continue; // skip + } + if (this.valuesAreEqual(override.getName(), name)) { + return override; + } + } + return null; + } + + + // ********** code completion ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (R override : this.getOverrides()) { + result = override.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + for (R override: this.getOverrides()) { + override.validate(messages, reporter, astRoot); + } + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + Annotation annotation = this.getValidationAnnotation(); + return (annotation != null) ? + annotation.getTextRange(astRoot) : + this.owner.getValidationTextRange(astRoot); + } + + protected Annotation getValidationAnnotation() { + JavaResourcePersistentMember resourceMember = this.getResourcePersistentMember(); + Annotation annotation = resourceMember.getAnnotation(this.getOverrideContainerAnnotationName()); + return (annotation != null) ? annotation : resourceMember.getAnnotation(this.getOverrideAnnotationName()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJarFile.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJarFile.java new file mode 100644 index 0000000000..16298f2d59 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJarFile.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.Vector; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.common.core.JptCommonCorePlugin; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.jpa.core.JpaStructureNode; +import org.eclipse.jpt.jpa.core.context.AccessType; +import org.eclipse.jpt.jpa.core.context.PersistentType; +import org.eclipse.jpt.jpa.core.context.java.JarFile; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.context.persistence.JarFileRef; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePackageFragmentRoot; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Context JAR file + */ +public class GenericJarFile + extends AbstractPersistenceXmlContextNode + implements JarFile, PersistentType.Owner +{ + protected final JavaResourcePackageFragmentRoot jarResourcePackageFragmentRoot; + + protected final Vector<JavaPersistentType> javaPersistentTypes = new Vector<JavaPersistentType>(); + protected final JavaPersistentTypeContainerAdapter javaPersistentTypeContainerAdapter = new JavaPersistentTypeContainerAdapter(); + + + // ********** constructor/initialization ********** + + public GenericJarFile(JarFileRef parent, JavaResourcePackageFragmentRoot jarResourcePackageFragmentRoot) { + super(parent); + this.jarResourcePackageFragmentRoot = jarResourcePackageFragmentRoot; + this.initializeJavaPersistentTypes(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncJavaPersistentTypes(); + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getJavaPersistentTypes()); + } + + public JavaResourcePackageFragmentRoot getJarResourcePackageFragmentRoot() { + return this.jarResourcePackageFragmentRoot; + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return null; + } + + public TextRange getSelectionTextRange() { + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + return null; + } + + public void dispose() { + // nothing yet + } + + + // ********** JpaContextNode implementation ********** + + @Override + public JptResourceType getResourceType() { + return JptCommonCorePlugin.JAR_RESOURCE_TYPE; + } + + + // ********** Java persistent types ********** + + public JavaPersistentType getPersistentType(String typeName) { + for (JavaPersistentType pt : this.getJavaPersistentTypes()) { + if (pt.getName().equals(typeName)) { + return pt; + } + } + return null; + } + + public Iterator<JavaPersistentType> javaPersistentTypes() { + return this.getJavaPersistentTypes().iterator(); + } + + protected Iterable<JavaPersistentType> getJavaPersistentTypes() { + return new LiveCloneIterable<JavaPersistentType>(this.javaPersistentTypes); + } + + public int javaPersistentTypesSize() { + return this.javaPersistentTypes.size(); + } + + protected void initializeJavaPersistentTypes() { + for (JavaResourcePersistentType jrpt : this.getJavaResourcePersistentTypes()) { + this.javaPersistentTypes.add(this.buildJavaPersistentType(jrpt)); + } + } + + protected void syncJavaPersistentTypes() { + ContextContainerTools.synchronizeWithResourceModel(this.javaPersistentTypeContainerAdapter); + } + + protected void addJavaPersistentType(JavaResourcePersistentType jrpt) { + JavaPersistentType javaPersistentType = this.buildJavaPersistentType(jrpt); + this.addItemToCollection(javaPersistentType, this.javaPersistentTypes, JAVA_PERSISTENT_TYPES_COLLECTION); + } + + protected void removeJavaPersistentType(JavaPersistentType javaPersistentType ) { + this.removeItemFromCollection(javaPersistentType, this.javaPersistentTypes, JAVA_PERSISTENT_TYPES_COLLECTION); + } + + /** + * the resource JAR holds only annotated types, so we can use them all for + * building the context types + */ + protected Iterable<JavaResourcePersistentType> getJavaResourcePersistentTypes() { + return CollectionTools.iterable(this.jarResourcePackageFragmentRoot.persistentTypes()); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + /** + * Java persistent type container adapter + */ + protected class JavaPersistentTypeContainerAdapter + implements ContextContainerTools.Adapter<JavaPersistentType, JavaResourcePersistentType> + { + public Iterable<JavaPersistentType> getContextElements() { + return GenericJarFile.this.getJavaPersistentTypes(); + } + public Iterable<JavaResourcePersistentType> getResourceElements() { + return GenericJarFile.this.getJavaResourcePersistentTypes(); + } + public JavaResourcePersistentType getResourceElement(JavaPersistentType contextElement) { + return contextElement.getResourcePersistentType(); + } + public void moveContextElement(int index, JavaPersistentType element) { + // ignore moves - we don't care about the order of the Java persistent types + } + public void addContextElement(int index, JavaResourcePersistentType resourceElement) { + // ignore the index - we don't care about the order of the Java persistent types + GenericJarFile.this.addJavaPersistentType(resourceElement); + } + public void removeContextElement(JavaPersistentType element) { + GenericJarFile.this.removeJavaPersistentType(element); + } + } + + + // ********** PersistentTypeContainer implementation ********** + + public Iterable<? extends PersistentType> getPersistentTypes() { + return this.getJavaPersistentTypes(); + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getDefaultPersistentTypeAccess() { + return this.getPersistenceUnit().getDefaultAccess(); + } + + public AccessType getOverridePersistentTypeAccess() { + // no access type at this level overrides any local access type specification + return null; + } + + + // ********** JpaNode implementation ********** + + @Override + public JarFileRef getParent() { + return (JarFileRef) super.getParent(); + } + + protected JarFileRef getJarFileRef() { + return this.getParent(); + } + + @Override + public IResource getResource() { + return this.jarResourcePackageFragmentRoot.getFile(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + // TODO validate 'javaPersistentTypes' + } + + public boolean isIn(org.eclipse.core.resources.IFolder folder) { + IResource member = folder.findMember(this.jarResourcePackageFragmentRoot.getFile().getName()); + IFile file = this.jarResourcePackageFragmentRoot.getFile(); + return member != null && file != null && member.equals(file); + } + + public TextRange getValidationTextRange() { + return this.getJarFileRef().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java new file mode 100644 index 0000000000..ebcec5ef3e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverride.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2008, 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.jpa1.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.ReadOnlyAssociationOverride; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +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.JavaOverrideRelationship; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaOverride; +import org.eclipse.jpt.jpa.core.resource.java.AssociationOverrideAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Specified Java association override + */ +public class GenericJavaAssociationOverride + extends AbstractJavaOverride<JavaAssociationOverrideContainer, AssociationOverrideAnnotation> + implements JavaAssociationOverride +{ + protected final JavaOverrideRelationship relationship; + + + public GenericJavaAssociationOverride(JavaAssociationOverrideContainer parent, AssociationOverrideAnnotation annotation) { + super(parent, annotation); + this.relationship = this.buildRelationship(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.relationship.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.relationship.update(); + } + + + // ********** specified/virtual ********** + + @Override + public JavaVirtualAssociationOverride convertToVirtual() { + return (JavaVirtualAssociationOverride) super.convertToVirtual(); + } + + + // ********** relationship ********** + + public JavaOverrideRelationship getRelationship() { + return this.relationship; + } + + protected JavaOverrideRelationship buildRelationship() { + return this.getJpaFactory().buildJavaOverrideRelationship(this); + } + + + // ********** misc ********** + + public RelationshipMapping getMapping() { + return this.getContainer().getRelationshipMapping(this.name); + } + + public void initializeFrom(ReadOnlyAssociationOverride oldOverride) { + super.initializeFrom(oldOverride); + this.relationship.initializeFrom(oldOverride.getRelationship()); + } + + public void initializeFromVirtual(ReadOnlyAssociationOverride virtualOverride) { + super.initializeFromVirtual(virtualOverride); + this.relationship.initializeFromVirtual(virtualOverride.getRelationship()); + } + + + // ********** 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; + } + + @Override + protected Iterator<String> candidateNames() { + return this.getContainer().allOverridableNames(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.relationship.validate(messages, reporter, astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java new file mode 100644 index 0000000000..4d672822da --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAssociationOverrideContainer.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.Table; +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.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaReadOnlyAssociationOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualAssociationOverride; +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.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.java.AssociationOverrideAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.AssociationOverridesAnnotation; + +/** + * Java attribute override container + */ +public class GenericJavaAssociationOverrideContainer + extends AbstractJavaOverrideContainer< + JavaAssociationOverrideContainer.Owner, + JavaReadOnlyAssociationOverride, + JavaAssociationOverride, + JavaVirtualAssociationOverride, + AssociationOverrideAnnotation + > + implements JavaAssociationOverrideContainer +{ + public GenericJavaAssociationOverrideContainer(JavaJpaContextNode parent, JavaAssociationOverrideContainer.Owner owner) { + super(parent, owner); + } + + + public RelationshipMapping getRelationshipMapping(String attributeName) { + return MappingTools.getRelationshipMapping(attributeName, this.owner.getOverridableTypeMapping()); + } + + public Relationship resolveOverriddenRelationship(String associationOverrideName) { + return this.owner.resolveOverriddenRelationship(associationOverrideName); + } + + public JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, org.eclipse.jpt.jpa.core.context.JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return this.owner.buildJoinTableJoinColumnValidator(override, column, owner, textRangeResolver); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, org.eclipse.jpt.jpa.core.context.JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return this.owner.buildJoinTableInverseJoinColumnValidator(override, column, owner, textRangeResolver); + } + + public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) { + return this.owner.buildTableValidator(override, table, textRangeResolver); + } + + @Override + protected String getOverrideAnnotationName() { + return AssociationOverrideAnnotation.ANNOTATION_NAME; + } + + @Override + protected String getOverrideContainerAnnotationName() { + return AssociationOverridesAnnotation.ANNOTATION_NAME; + } + + @Override + protected JavaAssociationOverride buildSpecifiedOverride(AssociationOverrideAnnotation overrideAnnotation) { + return this.getJpaFactory().buildJavaAssociationOverride(this, overrideAnnotation); + } + + @Override + protected void initializeSpecifiedOverride(JavaAssociationOverride specifiedOverride, JavaVirtualAssociationOverride virtualOverride) { + specifiedOverride.initializeFromVirtual(virtualOverride); + } + + @Override + protected JavaVirtualAssociationOverride buildVirtualOverride(String name) { + return this.getJpaFactory().buildJavaVirtualAssociationOverride(this, name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java new file mode 100644 index 0000000000..dda23b1611 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverride.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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.jpa1.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.CollectionTools; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyAttributeOverride; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverride; +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.JavaVirtualAttributeOverride; +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.context.java.AbstractJavaOverride; +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.AttributeOverrideAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.CompleteColumnAnnotation; +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; + +/** + * Specified Java attribute override + */ +public class GenericJavaAttributeOverride + extends AbstractJavaOverride<JavaAttributeOverrideContainer, AttributeOverrideAnnotation> + implements JavaAttributeOverride, JavaColumn.Owner +{ + protected final JavaColumn column; + + + public GenericJavaAttributeOverride(JavaAttributeOverrideContainer parent, AttributeOverrideAnnotation annotation) { + super(parent, annotation); + this.column = this.buildColumn(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.column.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.column.update(); + } + + + // ********** specified/virtual ********** + + @Override + public JavaVirtualAttributeOverride convertToVirtual() { + return (JavaVirtualAttributeOverride) super.convertToVirtual(); + } + + + // ********** column ********** + + public JavaColumn getColumn() { + return this.column; + } + + protected JavaColumn buildColumn() { + return this.getJpaFactory().buildJavaColumn(this, this); + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyAttributeOverride oldOverride) { + super.initializeFrom(oldOverride); + this.column.initializeFrom(oldOverride.getColumn()); + } + + public void initializeFromVirtual(ReadOnlyAttributeOverride oldOverride) { + super.initializeFromVirtual(oldOverride); + this.column.initializeFromVirtual(oldOverride.getColumn()); + } + + + // ********** column owner implementation ********** + + public TypeMapping getTypeMapping() { + return this.getContainer().getTypeMapping(); + } + + public String getDefaultTableName() { + return this.getContainer().getDefaultTableName(); + } + + public Table resolveDbTable(String tableName) { + return this.getContainer().resolveDbTable(tableName); + } + + public String getDefaultColumnName() { + return this.name; + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return this.getContainer().buildColumnValidator(this, (BaseColumn) column, this, (BaseColumnTextRangeResolver) textRangeResolver); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.getContainer().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.getContainer().candidateTableNames(); + } + + public CompleteColumnAnnotation getColumnAnnotation() { + return this.getOverrideAnnotation().getNonNullColumn(); + } + + public void removeColumnAnnotation() { + this.getOverrideAnnotation().removeColumn(); + } + + + // ********** mapped by relationship ********** + + protected boolean isMappedByRelationship() { + return CollectionTools.contains(this.getMappedByRelationshipAttributeNames(), this.buildQualifier()); + } + + protected Iterable<String> getMappedByRelationshipAttributeNames() { + return TypeMappingTools.getMappedByRelationshipAttributeNames(this.getTypeMapping()); + } + + /** + * overridable names are (usually?) qualified with a container mapping, + * which may also be the one mapped by a relationship + */ + protected String buildQualifier() { + if (this.name == null) { + return null; + } + int index = this.name.indexOf('.'); + return (index == -1) ? this.name : this.name.substring(0, index); + } + + + // ********** 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; + } + return null; + } + + @Override + protected Iterator<String> candidateNames() { + return this.getContainer().allOverridableNames(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + // [JPA 2.0] if the column is specified, or if the override is not mapped by a relationship, + // then the column is validated. + // (In JPA 1.0, the column will always be validated, since the override is never mapped by a + // relationship) + if (this.columnAnnotationIsSpecified() || ! this.isMappedByRelationship()) { + this.column.validate(messages, reporter, astRoot); + } + + // [JPA 2.0] if the override is mapped by a relationship, then that actually is in itself + // a validation error + // (We prevent implied overrides that are mapped by a relationship ... hopefully) + // (In JPA 1.0, this will never occur) + if (this.isMappedByRelationship()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ATTRIBUTE_OVERRIDE_MAPPED_BY_RELATIONSHIP_AND_SPECIFIED, + EMPTY_STRING_ARRAY, + this, + this.getValidationTextRange(astRoot) + ) + ); + } + } + + protected boolean columnAnnotationIsSpecified() { + return this.getOverrideAnnotation().getColumn() != null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java new file mode 100644 index 0000000000..26be7c2ef8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaAttributeOverrideContainer.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaReadOnlyAttributeOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualAttributeOverride; +import org.eclipse.jpt.jpa.core.resource.java.AttributeOverrideAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.AttributeOverridesAnnotation; + +/** + * Java attribute override container + */ +public class GenericJavaAttributeOverrideContainer + extends AbstractJavaOverrideContainer< + JavaAttributeOverrideContainer.Owner, + JavaReadOnlyAttributeOverride, + JavaAttributeOverride, + JavaVirtualAttributeOverride, + AttributeOverrideAnnotation + > + implements JavaAttributeOverrideContainer +{ + public GenericJavaAttributeOverrideContainer(JavaJpaContextNode parent, JavaAttributeOverrideContainer.Owner owner) { + super(parent, owner); + } + + + public Column resolveOverriddenColumn(String attributeName) { + return (attributeName == null) ? null : this.owner.resolveOverriddenColumn(attributeName); + } + + @Override + protected String getOverrideAnnotationName() { + return AttributeOverrideAnnotation.ANNOTATION_NAME; + } + + @Override + protected String getOverrideContainerAnnotationName() { + return AttributeOverridesAnnotation.ANNOTATION_NAME; + } + + @Override + protected JavaAttributeOverride buildSpecifiedOverride(AttributeOverrideAnnotation overrideAnnotation) { + return this.getJpaFactory().buildJavaAttributeOverride(this, overrideAnnotation); + } + + @Override + protected void initializeSpecifiedOverride(JavaAttributeOverride specifiedOverride, JavaVirtualAttributeOverride virtualOverride) { + specifiedOverride.initializeFromVirtual(virtualOverride); + } + + @Override + protected JavaVirtualAttributeOverride buildVirtualOverride(String name) { + return this.getJpaFactory().buildJavaVirtualAttributeOverride(this, name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaBasicMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaBasicMapping.java new file mode 100644 index 0000000000..fc88aeed80 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaBasicMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaBasicMapping; + +public class GenericJavaBasicMapping + extends AbstractJavaBasicMapping +{ + public GenericJavaBasicMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaCascade.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaCascade.java new file mode 100644 index 0000000000..321792eaf2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaCascade.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * 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.jpa1.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.JavaRelationshipMapping; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaRelationshipMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaCascade2_0; +import org.eclipse.jpt.jpa.core.jpa2.resource.java.RelationshipMapping2_0Annotation; +import org.eclipse.jpt.jpa.core.resource.java.RelationshipMappingAnnotation; + +public class GenericJavaCascade + extends AbstractJavaJpaContextNode + implements JavaCascade2_0 +{ + protected boolean all; + + protected boolean persist; + + protected boolean merge; + + protected boolean remove; + + protected boolean refresh; + + /* JPA 2.0 */ + protected boolean detach; + + + /** + * This is built directly by the mapping implementation; as opposed to via + * a platform-specific factory. + * @see AbstractJavaRelationshipMapping#buildCascade() + */ + public GenericJavaCascade(JavaRelationshipMapping parent) { + super(parent); + this.all = this.buildAll(); + this.persist = this.buildPersist(); + this.merge = this.buildMerge(); + this.remove = this.buildRemove(); + this.refresh = this.buildRefresh(); + this.detach = this.buildDetach(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setAll_(this.buildAll()); + this.setPersist_(this.buildPersist()); + this.setMerge_(this.buildMerge()); + this.setRemove_(this.buildRemove()); + this.setRefresh_(this.buildRefresh()); + this.setDetach_(this.buildDetach()); + } + + + // ********** all ********** + + public boolean isAll() { + return this.all; + } + + public void setAll(boolean all) { + if (all != this.all) { + this.getMappingAnnotationForUpdate().setCascadeAll(all); + this.setAll_(all); + } + } + + protected void setAll_(boolean all) { + boolean old = this.all; + this.all = all; + this.firePropertyChanged(ALL_PROPERTY, old, all); + } + + protected boolean buildAll() { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation != null) && annotation.isCascadeAll(); + } + + + // ********** persist ********** + + public boolean isPersist() { + return this.persist; + } + + public void setPersist(boolean persist) { + if (persist != this.persist) { + this.getMappingAnnotationForUpdate().setCascadePersist(persist); + this.setPersist_(persist); + } + } + + protected void setPersist_(boolean persist) { + boolean old = this.persist; + this.persist = persist; + this.firePropertyChanged(PERSIST_PROPERTY, old, persist); + } + + protected boolean buildPersist() { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation != null) && annotation.isCascadePersist(); + } + + + // ********** merge ********** + + public boolean isMerge() { + return this.merge; + } + + public void setMerge(boolean merge) { + if (merge != this.merge) { + this.getMappingAnnotationForUpdate().setCascadeMerge(merge); + this.setMerge_(merge); + } + } + + protected void setMerge_(boolean merge) { + boolean old = this.merge; + this.merge = merge; + this.firePropertyChanged(MERGE_PROPERTY, old, merge); + } + + protected boolean buildMerge() { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation != null) && annotation.isCascadeMerge(); + } + + + // ********** remove ********** + + public boolean isRemove() { + return this.remove; + } + + public void setRemove(boolean remove) { + if (remove != this.remove) { + this.getMappingAnnotationForUpdate().setCascadeRemove(remove); + this.setRemove_(remove); + } + } + + protected void setRemove_(boolean remove) { + boolean oldRemove = this.remove; + this.remove = remove; + this.firePropertyChanged(REMOVE_PROPERTY, oldRemove, remove); + } + + protected boolean buildRemove() { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation != null) && annotation.isCascadeRemove(); + } + + + // ********** refresh ********** + + public boolean isRefresh() { + return this.refresh; + } + + public void setRefresh(boolean refresh) { + if (refresh != this.refresh) { + this.getMappingAnnotationForUpdate().setCascadeRefresh(refresh); + this.setRefresh_(refresh); + } + } + + protected void setRefresh_(boolean refresh) { + boolean old = this.refresh; + this.refresh = refresh; + this.firePropertyChanged(REFRESH_PROPERTY, old, refresh); + } + + protected boolean buildRefresh() { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation != null) && annotation.isCascadeRefresh(); + } + + + // ********** detach ********** + + public boolean isDetach() { + return this.detach; + } + + public void setDetach(boolean detach) { + if (detach != this.detach) { + this.getMappingAnnotationForUpdate2_0().setCascadeDetach(detach); + this.setDetach_(detach); + } + } + + protected void setDetach_(boolean detach) { + boolean old = this.detach; + this.detach = detach; + this.firePropertyChanged(DETACH_PROPERTY, old, detach); + } + + protected boolean buildDetach() { + return this.isJpa2_0Compatible() && this.buildDetach_(); + } + + protected boolean buildDetach_() { + RelationshipMapping2_0Annotation annotation = this.getMappingAnnotation2_0(); + return (annotation != null) && annotation.isCascadeDetach(); + } + + + + // ********** misc ********** + + @Override + public JavaRelationshipMapping getParent() { + return (JavaRelationshipMapping) super.getParent(); + } + + protected JavaRelationshipMapping getMapping() { + return this.getParent(); + } + + protected RelationshipMappingAnnotation getMappingAnnotation() { + return this.getMapping().getMappingAnnotation(); + } + + protected RelationshipMappingAnnotation getMappingAnnotationForUpdate() { + return this.getMapping().getAnnotationForUpdate(); + } + + protected RelationshipMapping2_0Annotation getMappingAnnotation2_0() { + return (RelationshipMapping2_0Annotation) this.getMappingAnnotation(); + } + + protected RelationshipMapping2_0Annotation getMappingAnnotationForUpdate2_0() { + return (RelationshipMapping2_0Annotation) this.getMappingAnnotationForUpdate(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + RelationshipMappingAnnotation annotation = this.getMappingAnnotation(); + return (annotation == null) ? null : annotation.getCascadeTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaColumn.java new file mode 100644 index 0000000000..2af11ca6fa --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaColumn.java @@ -0,0 +1,221 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.ReadOnlyColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaBaseColumn; +import org.eclipse.jpt.jpa.core.resource.java.CompleteColumnAnnotation; + +/** + * Java column + * <p> + * Note: The <code>Column</code> annotation is one of only 2 annotations that + * can be nested outside of an array (i.e. in an <code>AttributeOverride</code> + * annotation); the other is {@link GenericJavaJoinTable JoinTable}. + */ +public class GenericJavaColumn + extends AbstractJavaBaseColumn<CompleteColumnAnnotation, JavaColumn.Owner> + implements JavaColumn +{ + protected Integer specifiedLength; + protected int defaultLength; + + protected Integer specifiedPrecision; + protected int defaultPrecision; + + protected Integer specifiedScale; + protected int defaultScale; + + + public GenericJavaColumn(JavaJpaContextNode parent, JavaColumn.Owner owner) { + super(parent, owner); + this.specifiedLength = this.buildSpecifiedLength(); + this.specifiedPrecision = this.buildSpecifiedPrecision(); + this.specifiedScale = this.buildSpecifiedScale(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedLength_(this.buildSpecifiedLength()); + this.setSpecifiedPrecision_(this.buildSpecifiedPrecision()); + this.setSpecifiedScale_(this.buildSpecifiedScale()); + } + + @Override + public void update() { + super.update(); + this.setDefaultLength(this.buildDefaultLength()); + this.setDefaultPrecision(this.buildDefaultPrecision()); + this.setDefaultScale(this.buildDefaultScale()); + } + + + // ********** column annotation ********** + + @Override + public CompleteColumnAnnotation getColumnAnnotation() { + return this.owner.getColumnAnnotation(); + } + + @Override + protected void removeColumnAnnotation() { + this.owner.removeColumnAnnotation(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.defaultLength; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer length) { + if (this.valuesAreDifferent(this.specifiedLength, length)) { + this.getColumnAnnotation().setLength(length); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedLength_(length); + } + } + + protected void setSpecifiedLength_(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + return this.getColumnAnnotation().getLength(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int length) { + int old = this.defaultLength; + this.defaultLength = length; + this.firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, length); + } + + protected int buildDefaultLength() { + return DEFAULT_LENGTH; + } + + + // ********** precision ********** + + public int getPrecision() { + return (this.specifiedPrecision != null) ? this.specifiedPrecision.intValue() : this.defaultPrecision; + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + public void setSpecifiedPrecision(Integer precision) { + if (this.valuesAreDifferent(this.specifiedPrecision, precision)) { + this.getColumnAnnotation().setPrecision(precision); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedPrecision_(precision); + } + } + + protected void setSpecifiedPrecision_(Integer precision) { + Integer old = this.specifiedPrecision; + this.specifiedPrecision = precision; + this.firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, old, precision); + } + + protected Integer buildSpecifiedPrecision() { + return this.getColumnAnnotation().getPrecision(); + } + + public int getDefaultPrecision() { + return this.defaultPrecision; + } + + protected void setDefaultPrecision(int precision) { + int old = this.defaultPrecision; + this.defaultPrecision = precision; + this.firePropertyChanged(DEFAULT_PRECISION_PROPERTY, old, precision); + } + + protected int buildDefaultPrecision() { + return DEFAULT_PRECISION; + } + + + // ********** scale ********** + + public int getScale() { + return (this.specifiedScale != null) ? this.specifiedScale.intValue() : this.defaultScale; + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + public void setSpecifiedScale(Integer scale) { + if (this.valuesAreDifferent(this.specifiedScale, scale)) { + this.getColumnAnnotation().setScale(scale); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedScale_(scale); + } + } + + protected void setSpecifiedScale_(Integer scale) { + Integer old = this.specifiedScale; + this.specifiedScale = scale; + this.firePropertyChanged(SPECIFIED_SCALE_PROPERTY, old, scale); + } + + protected Integer buildSpecifiedScale() { + return this.getColumnAnnotation().getScale(); + } + + public int getDefaultScale() { + return this.defaultScale; + } + + protected void setDefaultScale(int scale) { + int old = this.defaultScale; + this.defaultScale = scale; + this.firePropertyChanged(DEFAULT_SCALE_PROPERTY, old, scale); + } + + protected int buildDefaultScale() { + return DEFAULT_SCALE; + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyColumn oldColumn) { + super.initializeFrom(oldColumn); + this.setSpecifiedLength(oldColumn.getSpecifiedLength()); + this.setSpecifiedPrecision(oldColumn.getSpecifiedPrecision()); + this.setSpecifiedScale(oldColumn.getSpecifiedScale()); + } + + public void initializeFromVirtual(ReadOnlyColumn virtualColumn) { + super.initializeFromVirtual(virtualColumn); + // ignore other settings? + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java new file mode 100644 index 0000000000..a88cc6660c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaDiscriminatorColumn.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.DiscriminatorType; +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.JavaPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaNamedColumn; +import org.eclipse.jpt.jpa.core.resource.java.DiscriminatorColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; + +/** + * Java discriminator column + */ +public class GenericJavaDiscriminatorColumn + extends AbstractJavaNamedColumn<DiscriminatorColumnAnnotation, JavaDiscriminatorColumn.Owner> + implements JavaDiscriminatorColumn +{ + protected DiscriminatorType specifiedDiscriminatorType; + protected DiscriminatorType defaultDiscriminatorType; + + protected Integer specifiedLength; + protected int defaultLength; + + + public GenericJavaDiscriminatorColumn(JavaEntity parent, JavaDiscriminatorColumn.Owner owner) { + super(parent, owner); + this.specifiedDiscriminatorType = this.buildSpecifiedDiscriminatorType(); + this.specifiedLength = this.buildSpecifiedLength(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedDiscriminatorType_(this.buildSpecifiedDiscriminatorType()); + this.setSpecifiedLength_(this.buildSpecifiedLength()); + } + + @Override + public void update() { + super.update(); + this.setDefaultDiscriminatorType(this.buildDefaultDiscriminatorType()); + this.setDefaultLength(this.buildDefaultLength()); + } + + + // ********** column annotation ********** + + @Override + public DiscriminatorColumnAnnotation getColumnAnnotation() { + return (DiscriminatorColumnAnnotation) this.getResourcePersistentType().getNonNullAnnotation(DiscriminatorColumnAnnotation.ANNOTATION_NAME); + } + + @Override + protected void removeColumnAnnotation() { + this.getResourcePersistentType().removeAnnotation(DiscriminatorColumnAnnotation.ANNOTATION_NAME); + } + + + // ********** discriminator type ********** + + public DiscriminatorType getDiscriminatorType() { + return (this.specifiedDiscriminatorType != null) ? this.specifiedDiscriminatorType : this.defaultDiscriminatorType; + } + + public DiscriminatorType getSpecifiedDiscriminatorType() { + return this.specifiedDiscriminatorType; + } + + public void setSpecifiedDiscriminatorType(DiscriminatorType discriminatorType) { + if (this.valuesAreDifferent(this.specifiedDiscriminatorType, discriminatorType)) { + this.getColumnAnnotation().setDiscriminatorType(DiscriminatorType.toJavaResourceModel(discriminatorType)); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedDiscriminatorType_(discriminatorType); + } + } + + protected void setSpecifiedDiscriminatorType_(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = discriminatorType; + this.firePropertyChanged(SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + protected DiscriminatorType buildSpecifiedDiscriminatorType() { + return DiscriminatorType.fromJavaResourceModel(this.getColumnAnnotation().getDiscriminatorType()); + } + + public DiscriminatorType getDefaultDiscriminatorType() { + return this.defaultDiscriminatorType; + } + + protected void setDefaultDiscriminatorType(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.defaultDiscriminatorType; + this.defaultDiscriminatorType = discriminatorType; + this.firePropertyChanged(DEFAULT_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + protected DiscriminatorType buildDefaultDiscriminatorType() { + return this.owner.getDefaultDiscriminatorType(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.defaultLength; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer length) { + if (this.valuesAreDifferent(this.specifiedLength, length)) { + this.getColumnAnnotation().setLength(length); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedLength_(length); + } + } + + protected void setSpecifiedLength_(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + return this.getColumnAnnotation().getLength(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int length) { + int old = this.defaultLength; + this.defaultLength = length; + this.firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, length); + } + + protected int buildDefaultLength() { + return this.owner.getDefaultLength(); + } + + + // ********** misc ********** + + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + protected JavaEntity getEntity() { + return this.getParent(); + } + + protected JavaPersistentType getPersistentType() { + return this.getEntity().getPersistentType(); + } + + protected JavaResourcePersistentType getResourcePersistentType() { + return this.getPersistentType().getResourcePersistentType(); + } + + + // ********** validation ********** + + public boolean isResourceSpecified() { + return this.getColumnAnnotation().isSpecified(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddable.java new file mode 100644 index 0000000000..75bcc8579a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddable.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.java; + +import org.eclipse.jpt.common.utility.internal.ArrayTools; +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaEmbeddable; +import org.eclipse.jpt.jpa.core.resource.java.EmbeddableAnnotation; + +/** + * Java embeddable type mapping + */ +public class GenericJavaEmbeddable + extends AbstractJavaEmbeddable +{ + public GenericJavaEmbeddable(JavaPersistentType parent, EmbeddableAnnotation mappingAnnotation) { + super(parent, mappingAnnotation); + } + + @Override + public boolean attributeMappingKeyAllowed(String attributeMappingKey) { + //generic only allows basic and transient within an Embeddable + return ArrayTools.contains(ALLOWED_ATTRIBUTE_MAPPING_KEYS, attributeMappingKey); + } + + public static final String[] ALLOWED_ATTRIBUTE_MAPPING_KEYS = + new String[] { + MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY, + MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY + }; +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java new file mode 100644 index 0000000000..2db8014c83 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedIdMapping.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.jpa.core.MappingKeys; +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.JavaEmbeddedIdMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTools; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaBaseEmbeddedMapping; +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.EmbeddedIdMapping2_0; +import org.eclipse.jpt.jpa.core.resource.java.EmbeddedIdAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java embedded ID mapping + */ +public class GenericJavaEmbeddedIdMapping + extends AbstractJavaBaseEmbeddedMapping<EmbeddedIdAnnotation> + implements EmbeddedIdMapping2_0, JavaEmbeddedIdMapping +{ + /* 2.0 feature - a relationship may map this embedded id */ + protected boolean mappedByRelationship; + + + public GenericJavaEmbeddedIdMapping(JavaPersistentAttribute parent) { + super(parent); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.setMappedByRelationship(this.buildMappedByRelationship()); + } + + + // ********** mapped by relationship ********** + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean value) { + boolean old = this.mappedByRelationship; + this.mappedByRelationship = value; + this.firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, old, value); + } + + 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.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY; + } + + @Override + protected String getAnnotationName() { + return EmbeddedIdAnnotation.ANNOTATION_NAME; + } + + @Override + protected Iterator<String> embeddableOverridableAttributeMappingNames() { + return (this.mappedByRelationship) ? + EmptyIterator.<String>instance() : + super.embeddableOverridableAttributeMappingNames(); + } + + @Override + protected JavaAttributeOverrideContainer.Owner buildAttributeOverrideContainerOwner() { + return new AttributeOverrideContainerOwner(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + // [JPA 2.0] if the embedded id is mapped by a relationship, then any specified + // attribute overrides are in error + // (in JPA 1.0, this will obviously never be reached) + if (this.mappedByRelationship + && (this.attributeOverrideContainer.specifiedOverridesSize() > 0)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.EMBEDDED_ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_ATTRIBUTE_OVERRIDES_SPECIFIED, + EMPTY_STRING_ARRAY, + this.attributeOverrideContainer, + this.attributeOverrideContainer.getValidationTextRange(astRoot) + ) + ); + } + } + + // ********** attribute override container owner ********* + + protected class AttributeOverrideContainerOwner + extends AbstractJavaBaseEmbeddedMapping<EmbeddedIdAnnotation>.AttributeOverrideContainerOwner + { + @Override + public Iterator<String> allOverridableNames() { + return GenericJavaEmbeddedIdMapping.this.isMappedByRelationship() ? + EmptyIterator.<String>instance() : + super.allOverridableNames(); + } + + @Override + protected Iterator<String> allOverridableAttributeNames_(TypeMapping typeMapping) { + final Set<String> mappedByRelationshipAttributeNames = this.buildMappedByRelationshipAttributeNames(); + if (mappedByRelationshipAttributeNames.isEmpty()) { + return super.allOverridableAttributeNames_(typeMapping); + } + return new FilteringIterator<String>(super.allOverridableAttributeNames_(typeMapping)) { + @Override + protected boolean accept(String attributeName) { + // overridable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + int dotIndex = attributeName.indexOf('.'); + String qualifier = (dotIndex > 0) ? attributeName.substring(0, dotIndex) : attributeName; + return ! mappedByRelationshipAttributeNames.contains(qualifier); + } + }; + } + + protected Set<String> buildMappedByRelationshipAttributeNames() { + return CollectionTools.set(GenericJavaEmbeddedIdMapping.this.getMappedByRelationshipAttributeNames()); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java new file mode 100644 index 0000000000..660bc2d6af --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEmbeddedMapping.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * 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.jpa1.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.jpa.core.MappingKeys; +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.BaseColumn; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.OverrideContainer; +import org.eclipse.jpt.jpa.core.context.Override_; +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaAssociationOverrideContainer; +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.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.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaBaseEmbeddedMapping; +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.EmbeddableOverrideDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinTableTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaEmbeddedMapping2_0; +import org.eclipse.jpt.jpa.core.resource.java.EmbeddedAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentMember; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java embedded mapping + */ +public class GenericJavaEmbeddedMapping + extends AbstractJavaBaseEmbeddedMapping<EmbeddedAnnotation> + implements JavaEmbeddedMapping2_0 +{ + protected final JavaAssociationOverrideContainer associationOverrideContainer; + + + public GenericJavaEmbeddedMapping(JavaPersistentAttribute parent) { + super(parent); + this.associationOverrideContainer = this.buildAssociationOverrideContainer(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.associationOverrideContainer.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.associationOverrideContainer.update(); + } + + + // ********** association override container ********** + + protected JavaAssociationOverrideContainer buildAssociationOverrideContainer() { + return this.isJpa2_0Compatible() ? + this.getJpaFactory2_0().buildJavaAssociationOverrideContainer(this, this.buildAssociationOverrideContainerOwner()) : + new GenericJavaAssociationOverrideContainer(this, null); + } + + public JavaAssociationOverrideContainer getAssociationOverrideContainer() { + return this.associationOverrideContainer; + } + + protected JavaAssociationOverrideContainer.Owner buildAssociationOverrideContainerOwner() { + return new AssociationOverrideContainerOwner(); + } + + + // ********** embedded mappings ********** + + /** + * This is only to build the choices for a "mapped by" setting in a + * relationship mapping. JPA 2.0 does not support relationship mappings + * in an embedded ID class; so we only put this logic here. + */ + @Override + @SuppressWarnings("unchecked") + public Iterator<String> allMappingNames() { + return this.isJpa2_0Compatible() ? + new CompositeIterator<String>(super.allMappingNames(), this.allEmbeddableAttributeMappingNames()) : + super.allMappingNames(); + } + + protected Iterator<String> allEmbeddableAttributeMappingNames() { + return this.qualifiedEmbeddableOverridableMappingNames(AttributeMappingTools.ALL_MAPPING_NAMES_TRANSFORMER); + } + + @Override + public AttributeMapping resolveAttributeMapping(String attributeName) { + AttributeMapping resolvedMapping = super.resolveAttributeMapping(attributeName); + if (resolvedMapping != null) { + return resolvedMapping; + } + return this.isJpa2_0Compatible() ? this.resolveAttributeMapping_(attributeName) : null; + } + + protected AttributeMapping resolveAttributeMapping_(String attributeName) { + attributeName = this.unqualify(attributeName); + if (attributeName == null) { + return null; + } + // recurse into the embeddable mappings + for (AttributeMapping mapping : CollectionTools.iterable(this.embeddableAttributeMappings())) { + AttributeMapping resolvedMapping = mapping.resolveAttributeMapping(attributeName); + if (resolvedMapping != null) { + return resolvedMapping; + } + } + return null; + } + + + // ********** misc ********** + + public String getKey() { + return MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY; + } + + @Override + protected String getAnnotationName() { + return EmbeddedAnnotation.ANNOTATION_NAME; + } + + @Override + public Relationship resolveOverriddenRelationship(String attributeName) { + return this.isJpa2_0Compatible() ? this.resolveOverriddenRelationship_(attributeName) : null; + } + + protected Relationship resolveOverriddenRelationship_(String attributeName) { + attributeName = this.unqualify(attributeName); + if (attributeName == null) { + return null; + } + AssociationOverride override = this.associationOverrideContainer.getSpecifiedOverrideNamed(attributeName); + // recurse into the target embeddable if necessary + return (override != null) ? override.getRelationship() : this.resolveOverriddenRelationshipInTargetEmbeddable(attributeName); + } + + protected Relationship resolveOverriddenRelationshipInTargetEmbeddable(String attributeName) { + return (this.targetEmbeddable == null) ? null : this.targetEmbeddable.resolveOverriddenRelationship(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.associationOverrideContainer.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + + return null; + } + + + // ********** validation ********** + + @Override + protected void validateOverrides(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validateOverrides(messages, reporter, astRoot); + this.associationOverrideContainer.validate(messages, reporter, astRoot); + } + + + // ********** association override container owner ********** + + protected class AssociationOverrideContainerOwner + implements JavaAssociationOverrideContainer.Owner + { + public JavaResourcePersistentMember getResourcePersistentMember() { + return GenericJavaEmbeddedMapping.this.getResourcePersistentAttribute(); + } + + public TypeMapping getTypeMapping() { + return GenericJavaEmbeddedMapping.this.getTypeMapping(); + } + + public TypeMapping getOverridableTypeMapping() { + return GenericJavaEmbeddedMapping.this.getTargetEmbeddable(); + } + + public Iterator<String> allOverridableNames() { + TypeMapping typeMapping = this.getOverridableTypeMapping(); + return (typeMapping != null) ? typeMapping.allOverridableAssociationNames() : EmptyIterator.<String>instance(); + } + + public Relationship resolveOverriddenRelationship(String attributeName) { + return MappingTools.resolveOverriddenRelationship(this.getOverridableTypeMapping(), attributeName); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.getTypeMapping().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.getTypeMapping().allAssociatedTableNames(); + } + + public org.eclipse.jpt.jpa.db.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 GenericJavaEmbeddedMapping.this.getValidationTextRange(astRoot); + } + + public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) { + return new AssociationOverrideValidator((AssociationOverride) override, (AssociationOverrideContainer) container, textRangeResolver, new EmbeddableOverrideDescriptionProvider()); + } + + 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, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return new AssociationOverrideInverseJoinColumnValidator(override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider()); + } + + public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) { + return new AssociationOverrideJoinTableValidator(override, (JoinTable) table, textRangeResolver); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEntity.java new file mode 100644 index 0000000000..e123367631 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEntity.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaEntity; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.NullJavaCacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.Cacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.CacheableHolder2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaCacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.jpa.core.resource.java.EntityAnnotation; + +public class GenericJavaEntity + extends AbstractJavaEntity +{ + // EclipseLink holds its cacheable in its caching + protected final JavaCacheable2_0 cacheable; + + + public GenericJavaEntity(JavaPersistentType parent, EntityAnnotation mappingAnnotation) { + super(parent, mappingAnnotation); + this.cacheable = this.buildCacheable(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.cacheable.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.cacheable.update(); + } + + + // ********** cacheable ********** + + public JavaCacheable2_0 getCacheable() { + return this.cacheable; + } + + protected JavaCacheable2_0 buildCacheable() { + return this.isJpa2_0Compatible() ? + this.getJpaFactory2_0().buildJavaCacheable(this) : + new NullJavaCacheable2_0(this); + } + + public boolean calculateDefaultCacheable() { + Cacheable2_0 parentCacheable = this.getParentCacheable(); + return (parentCacheable != null) ? + parentCacheable.isCacheable() : + ((PersistenceUnit2_0) this.getPersistenceUnit()).calculateDefaultCacheable(); + } + + protected Cacheable2_0 getParentCacheable() { + CacheableHolder2_0 parentEntity = (CacheableHolder2_0) this.getParentEntity(); + return (parentEntity == null) ? null : parentEntity.getCacheable(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java new file mode 100644 index 0000000000..0ef279813f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaEnumeratedConverter.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.EnumType; +import org.eclipse.jpt.jpa.core.context.EnumeratedConverter; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaEnumeratedConverter; +import org.eclipse.jpt.jpa.core.resource.java.EnumeratedAnnotation; + +public class GenericJavaEnumeratedConverter + extends AbstractJavaConverter + implements JavaEnumeratedConverter +{ + protected final EnumeratedAnnotation enumeratedAnnotation; + + protected EnumType specifiedEnumType; + protected EnumType defaultEnumType; + + + public GenericJavaEnumeratedConverter(JavaAttributeMapping parent, EnumeratedAnnotation enumeratedAnnotation) { + super(parent); + this.enumeratedAnnotation = enumeratedAnnotation; + this.specifiedEnumType = this.buildSpecifiedEnumType(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedEnumType_(this.buildSpecifiedEnumType()); + } + + @Override + public void update() { + super.update(); + this.setDefaultEnumType(this.buildDefaultEnumType()); + } + + + // ********** enum type ********** + + public EnumType getEnumType() { + return (this.specifiedEnumType != null) ? this.specifiedEnumType : this.defaultEnumType; + } + + public EnumType getSpecifiedEnumType() { + return this.specifiedEnumType; + } + + public void setSpecifiedEnumType(EnumType enumType) { + this.enumeratedAnnotation.setValue(EnumType.toJavaResourceModel(enumType)); + this.setSpecifiedEnumType_(enumType); + } + + protected void setSpecifiedEnumType_(EnumType enumType) { + EnumType old = this.specifiedEnumType; + this.specifiedEnumType = enumType; + this.firePropertyChanged(SPECIFIED_ENUM_TYPE_PROPERTY, old, enumType); + } + + protected EnumType buildSpecifiedEnumType() { + return EnumType.fromJavaResourceModel(this.enumeratedAnnotation.getValue()); + } + + public EnumType getDefaultEnumType() { + return this.defaultEnumType; + } + + protected void setDefaultEnumType(EnumType enumType) { + EnumType old = this.defaultEnumType; + this.defaultEnumType = enumType; + this.firePropertyChanged(DEFAULT_ENUM_TYPE_PROPERTY, old, enumType); + } + + protected EnumType buildDefaultEnumType() { + return DEFAULT_ENUM_TYPE; + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return EnumeratedConverter.class; + } + + @Override + protected String getAnnotationName() { + return EnumeratedAnnotation.ANNOTATION_NAME; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.enumeratedAnnotation.getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java new file mode 100644 index 0000000000..de5501141b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratedValue.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * 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.jpa1.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.GenerationType; +import org.eclipse.jpt.jpa.core.context.Generator; +import org.eclipse.jpt.jpa.core.context.java.JavaGeneratedValue; +import org.eclipse.jpt.jpa.core.context.java.JavaIdMapping; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +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.GeneratedValueAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java generated value + */ +public class GenericJavaGeneratedValue + extends AbstractJavaJpaContextNode + implements JavaGeneratedValue +{ + protected final GeneratedValueAnnotation generatedValueAnnotation; + + protected GenerationType specifiedStrategy; + protected GenerationType defaultStrategy; + + protected String specifiedGenerator; + protected String defaultGenerator; + + + public GenericJavaGeneratedValue(JavaIdMapping parent, GeneratedValueAnnotation generatedValueAnnotation) { + super(parent); + this.generatedValueAnnotation = generatedValueAnnotation; + this.specifiedStrategy = this.buildSpecifiedStrategy(); + this.specifiedGenerator = generatedValueAnnotation.getGenerator(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedStrategy_(this.buildSpecifiedStrategy()); + this.setSpecifiedGenerator_(this.generatedValueAnnotation.getGenerator()); + } + + @Override + public void update() { + super.update(); + this.setDefaultStrategy(this.buildDefaultStrategy()); + this.setDefaultGenerator(this.buildDefaultGenerator()); + } + + + // ********** strategy ********** + + public GenerationType getStrategy() { + return (this.specifiedStrategy != null) ? this.specifiedStrategy : this.defaultStrategy; + } + + public GenerationType getSpecifiedStrategy() { + return this.specifiedStrategy; + } + + public void setSpecifiedStrategy(GenerationType strategy) { + this.generatedValueAnnotation.setStrategy(GenerationType.toJavaResourceModel(strategy)); + this.setSpecifiedStrategy_(strategy); + } + + protected void setSpecifiedStrategy_(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + protected GenerationType buildSpecifiedStrategy() { + return GenerationType.fromJavaResourceModel(this.generatedValueAnnotation.getStrategy()); + } + + public GenerationType getDefaultStrategy() { + return this.defaultStrategy; + } + + protected void setDefaultStrategy(GenerationType strategy) { + GenerationType old = this.defaultStrategy; + this.defaultStrategy = strategy; + this.firePropertyChanged(DEFAULT_STRATEGY_PROPERTY, old, strategy); + } + + protected GenerationType buildDefaultStrategy() { + return DEFAULT_STRATEGY; + } + + + // ********** generator ********** + + public String getGenerator() { + return (this.specifiedGenerator != null) ? this.specifiedGenerator : this.defaultGenerator; + } + + public String getSpecifiedGenerator() { + return this.specifiedGenerator; + } + + public void setSpecifiedGenerator(String generator) { + this.generatedValueAnnotation.setGenerator(generator); + this.setSpecifiedGenerator_(generator); + } + + protected void setSpecifiedGenerator_(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + public String getDefaultGenerator() { + return this.defaultGenerator; + } + + protected void setDefaultGenerator(String generator) { + String old = this.defaultGenerator; + this.defaultGenerator = generator; + this.firePropertyChanged(DEFAULT_GENERATOR_PROPERTY, old, generator); + } + + protected String buildDefaultGenerator() { + return null; + } + + public TextRange getGeneratorTextRange(CompilationUnit astRoot) { + return this.generatedValueAnnotation.getGeneratorTextRange(astRoot); + } + + + // ********** misc ********** + + public GeneratedValueAnnotation getGeneratedValueAnnotation() { + return this.generatedValueAnnotation; + } + + + // ********** 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.generatorTouches(pos, astRoot)) { + return this.javaCandidateGeneratorNames(filter); + } + return null; + } + + protected boolean generatorTouches(int pos, CompilationUnit astRoot) { + return this.generatedValueAnnotation.generatorTouches(pos, astRoot); + } + + protected Iterator<String> javaCandidateGeneratorNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.candidateGeneratorNames(filter)); + } + + protected Iterator<String> candidateGeneratorNames(Filter<String> filter) { + return new FilteringIterator<String>(this.candidateGeneratorNames(), filter); + } + + protected Iterator<String> candidateGeneratorNames() { + return this.getPersistenceUnit().getUniqueGeneratorNames().iterator(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + + String generator = this.getGenerator(); + if (generator == null) { + return; + } + + for (Iterator<Generator> stream = this.getPersistenceUnit().generators(); stream.hasNext(); ) { + if (generator.equals(stream.next().getName())) { + return; + } + } + + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME, + new String[] {generator}, + this.getParent(), + this.getGeneratorTextRange(astRoot) + ) + ); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.generatedValueAnnotation.getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java new file mode 100644 index 0000000000..65d1ab157d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaGeneratorContainer.java @@ -0,0 +1,283 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.Filter; +import org.eclipse.jpt.common.utility.internal.StringTools; +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.JavaGeneratorContainer; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaSequenceGenerator; +import org.eclipse.jpt.jpa.core.context.java.JavaTableGenerator; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +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.SequenceGeneratorAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.TableGeneratorAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaGeneratorContainer + extends AbstractJavaJpaContextNode + implements JavaGeneratorContainer +{ + protected final Owner owner; + + protected JavaSequenceGenerator sequenceGenerator; + + protected JavaTableGenerator tableGenerator; + + + public GenericJavaGeneratorContainer(JavaJpaContextNode parent, Owner owner) { + super(parent); + this.owner = owner; + this.sequenceGenerator = this.buildSequenceGenerator(); + this.tableGenerator = this.buildTableGenerator(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSequenceGenerator(); + this.syncTableGenerator(); + } + + @Override + public void update() { + super.update(); + if (this.sequenceGenerator != null) { + this.sequenceGenerator.update(); + } + if (this.tableGenerator != null) { + this.tableGenerator.update(); + } + } + + + // ********** sequence generator ********** + + public JavaSequenceGenerator getSequenceGenerator() { + return this.sequenceGenerator; + } + + public JavaSequenceGenerator addSequenceGenerator() { + if (this.sequenceGenerator != null) { + throw new IllegalStateException("sequence generator already exists: " + this.sequenceGenerator); //$NON-NLS-1$ + } + SequenceGeneratorAnnotation annotation = this.buildSequenceGeneratorAnnotation(); + JavaSequenceGenerator generator = this.buildSequenceGenerator(annotation); + this.setSequenceGenerator(generator); + return generator; + } + + protected SequenceGeneratorAnnotation buildSequenceGeneratorAnnotation() { + return (SequenceGeneratorAnnotation) this.owner.getResourceAnnotatedElement().addAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + } + + public void removeSequenceGenerator() { + if (this.sequenceGenerator == null) { + throw new IllegalStateException("sequence generator does not exist"); //$NON-NLS-1$ + } + this.owner.getResourceAnnotatedElement().removeAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + this.setSequenceGenerator(null); + } + + protected JavaSequenceGenerator buildSequenceGenerator() { + SequenceGeneratorAnnotation annotation = this.getSequenceGeneratorAnnotation(); + return (annotation == null) ? null : this.buildSequenceGenerator(annotation); + } + + protected SequenceGeneratorAnnotation getSequenceGeneratorAnnotation() { + return (SequenceGeneratorAnnotation) this.owner.getResourceAnnotatedElement().getAnnotation(SequenceGeneratorAnnotation.ANNOTATION_NAME); + } + + protected JavaSequenceGenerator buildSequenceGenerator(SequenceGeneratorAnnotation sequenceGeneratorAnnotation) { + return this.getJpaFactory().buildJavaSequenceGenerator(this, sequenceGeneratorAnnotation); + } + + protected void syncSequenceGenerator() { + SequenceGeneratorAnnotation annotation = this.getSequenceGeneratorAnnotation(); + if (annotation == null) { + if (this.sequenceGenerator != null) { + this.setSequenceGenerator(null); + } + } else { + if ((this.sequenceGenerator != null) && (this.sequenceGenerator.getGeneratorAnnotation() == annotation)) { + this.sequenceGenerator.synchronizeWithResourceModel(); + } else { + this.setSequenceGenerator(this.buildSequenceGenerator(annotation)); + } + } + } + + protected void setSequenceGenerator(JavaSequenceGenerator sequenceGenerator) { + JavaSequenceGenerator old = this.sequenceGenerator; + this.sequenceGenerator = sequenceGenerator; + this.firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, old, sequenceGenerator); + } + + + // ********** table generator ********** + + public JavaTableGenerator getTableGenerator() { + return this.tableGenerator; + } + + public JavaTableGenerator addTableGenerator() { + if (this.tableGenerator != null) { + throw new IllegalStateException("table generator already exists: " + this.tableGenerator); //$NON-NLS-1$ + } + TableGeneratorAnnotation annotation = this.buildTableGeneratorAnnotation(); + JavaTableGenerator generator = this.buildTableGenerator(annotation); + this.setTableGenerator(generator); + return generator; + } + + protected TableGeneratorAnnotation buildTableGeneratorAnnotation() { + return (TableGeneratorAnnotation) this.owner.getResourceAnnotatedElement().addAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + } + + public void removeTableGenerator() { + if (this.tableGenerator == null) { + throw new IllegalStateException("table generator does not exist"); //$NON-NLS-1$ + } + this.owner.getResourceAnnotatedElement().removeAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + this.setTableGenerator(null); + } + + protected JavaTableGenerator buildTableGenerator() { + TableGeneratorAnnotation annotation = this.getTableGeneratorAnnotation(); + return (annotation == null) ? null : this.buildTableGenerator(annotation); + } + + protected TableGeneratorAnnotation getTableGeneratorAnnotation() { + return (TableGeneratorAnnotation) this.owner.getResourceAnnotatedElement().getAnnotation(TableGeneratorAnnotation.ANNOTATION_NAME); + } + + protected JavaTableGenerator buildTableGenerator(TableGeneratorAnnotation tableGeneratorAnnotation) { + return this.getJpaFactory().buildJavaTableGenerator(this, tableGeneratorAnnotation); + } + + protected void syncTableGenerator() { + TableGeneratorAnnotation annotation = this.getTableGeneratorAnnotation(); + if (annotation == null) { + if (this.tableGenerator != null) { + this.setTableGenerator(null); + } + } else { + if ((this.tableGenerator != null) && (this.tableGenerator.getGeneratorAnnotation() == annotation)) { + this.tableGenerator.synchronizeWithResourceModel(); + } else { + this.setTableGenerator(this.buildTableGenerator(annotation)); + } + } + } + + protected void setTableGenerator(JavaTableGenerator tableGenerator) { + JavaTableGenerator old = this.tableGenerator; + this.tableGenerator = tableGenerator; + this.firePropertyChanged(TABLE_GENERATOR_PROPERTY, old, tableGenerator); + } + + + // ********** code completion ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.tableGenerator != null) { + result = this.tableGenerator.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + if (this.sequenceGenerator != null) { + result = this.sequenceGenerator.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.validateGenerators(messages, astRoot); + } + + protected void validateGenerators(List<IMessage> messages, CompilationUnit astRoot) { + for (JavaGenerator localGenerator : this.getGenerators()) { + String name = localGenerator.getName(); + if (StringTools.stringIsEmpty(name)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_NAME_UNDEFINED, + new String[] {}, + localGenerator, + localGenerator.getNameTextRange(astRoot) + ) + ); + } else { + List<String> reportedNames = new ArrayList<String>(); + for (Iterator<Generator> globalGenerators = this.getPersistenceUnit().generators(); globalGenerators.hasNext(); ) { + if (localGenerator.duplicates(globalGenerators.next()) && !reportedNames.contains(name)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_DUPLICATE_NAME, + new String[] {name}, + localGenerator, + localGenerator.getNameTextRange(astRoot) + ) + ); + reportedNames.add(name); + } + } + } + } + } + + protected Iterable<JavaGenerator> getGenerators() { + ArrayList<JavaGenerator> generators = new ArrayList<JavaGenerator>(); + this.addGeneratorsTo(generators); + return generators; + } + + protected void addGeneratorsTo(ArrayList<JavaGenerator> generators) { + if (this.sequenceGenerator != null) { + generators.add(this.sequenceGenerator); + } + if (this.tableGenerator != null) { + generators.add(this.tableGenerator); + } + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.owner.getResourceAnnotatedElement().getTextRange(astRoot); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaIdMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaIdMapping.java new file mode 100644 index 0000000000..7f1aca7b89 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaIdMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaIdMapping; + + +public class GenericJavaIdMapping + extends AbstractJavaIdMapping +{ + public GenericJavaIdMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinColumn.java new file mode 100644 index 0000000000..de4e5b0c85 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinColumn.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * 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.jpa1.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.iterables.EmptyIterable; +import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +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.java.AbstractJavaBaseColumn; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaNamedColumn; +import org.eclipse.jpt.jpa.core.internal.context.java.JavaJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation; +import org.eclipse.jpt.jpa.db.Column; +import org.eclipse.jpt.jpa.db.Table; + +/** + * Java join column + */ +public class GenericJavaJoinColumn + extends AbstractJavaBaseColumn<JoinColumnAnnotation, JavaJoinColumn.Owner> + implements JavaJoinColumn +{ + /** @see AbstractJavaNamedColumn#AbstractJavaNamedColumn(JavaJpaContextNode, org.eclipse.jpt.jpa.core.context.java.JavaNamedColumn.Owner, org.eclipse.jpt.jpa.core.resource.java.NamedColumnAnnotation) */ + protected /* final */ JoinColumnAnnotation columnAnnotation; // never null + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericJavaJoinColumn(JavaJpaContextNode parent, JavaJoinColumn.Owner owner) { + this(parent, owner, null); + } + + public GenericJavaJoinColumn(JavaJpaContextNode parent, JavaJoinColumn.Owner owner, JoinColumnAnnotation columnAnnotation) { + super(parent, owner, columnAnnotation); + this.specifiedReferencedColumnName = this.buildSpecifiedReferencedColumnName(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedReferencedColumnName_(this.buildSpecifiedReferencedColumnName()); + } + + @Override + public void update() { + super.update(); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** column annotation ********** + + @Override + public JoinColumnAnnotation getColumnAnnotation() { + return this.columnAnnotation; + } + + @Override + protected void setColumnAnnotation(JoinColumnAnnotation columnAnnotation) { + this.columnAnnotation = columnAnnotation; + } + + @Override + protected void removeColumnAnnotation() { + // we don't remove a join column annotation when it is empty + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String name) { + if (this.valuesAreDifferent(this.specifiedReferencedColumnName, name)) { + this.getColumnAnnotation().setReferencedColumnName(name); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedReferencedColumnName_(name); + } + } + + protected void setSpecifiedReferencedColumnName_(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return this.getColumnAnnotation().getReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.owner); + } + + public TextRange getReferencedColumnNameTextRange(CompilationUnit astRoot) { + TextRange textRange = this.getColumnAnnotation().getReferencedColumnNameTextRange(astRoot); + return (textRange != null) ? textRange : this.owner.getValidationTextRange(astRoot); + } + + + // ********** database stuff ********** + + public Table getReferencedColumnDbTable() { + return this.owner.getReferencedColumnDbTable(); + } + + protected Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public boolean referencedColumnIsResolved() { + return this.getReferencedDbColumn() != null; + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyJoinColumn oldColumn) { + super.initializeFrom(oldColumn); + this.setSpecifiedReferencedColumnName(oldColumn.getSpecifiedReferencedColumnName()); + } + + public void initializeFromVirtual(ReadOnlyJoinColumn virtualColumn) { + super.initializeFromVirtual(virtualColumn); + this.setSpecifiedReferencedColumnName(virtualColumn.getReferencedColumnName()); + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.owner); + } + + + // ********** 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.referencedColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateReferencedColumnNames(filter).iterator(); + } + return null; + } + + protected boolean referencedColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.getColumnAnnotation().referencedColumnNameTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateReferencedColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateReferencedColumnNames(filter)); + } + + protected Iterable<String> getCandidateReferencedColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateReferencedColumnNames(), filter); + } + + protected Iterable<String> getCandidateReferencedColumnNames() { + Table table = this.owner.getReferencedColumnDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + + // ********** validation ********** + + @Override + protected NamedColumnTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) { + return new JavaJoinColumnTextRangeResolver(this, astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinTable.java new file mode 100644 index 0000000000..cc6254661b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaJoinTable.java @@ -0,0 +1,496 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.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.Tools; +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.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.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTable; +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.JavaJoinTable; +import org.eclipse.jpt.jpa.core.context.java.JavaJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +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.resource.java.NullJoinColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation; +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; + +/** + * Java join table + * <p> + * Note: The <code>JoinTable</code> annotation is one of only 2 annotations that + * can be nested outside of an array (i.e. in an <code>AssociationOverride</code> + * annotation); the other is {@link GenericJavaColumn Column}. + */ +public class GenericJavaJoinTable + extends GenericJavaReferenceTable<JoinTableAnnotation> + implements JavaJoinTable +{ + protected final Vector<JavaJoinColumn> specifiedInverseJoinColumns = new Vector<JavaJoinColumn>(); + protected final SpecifiedInverseJoinColumnContainerAdapter specifiedInverseJoinColumnContainerAdapter = new SpecifiedInverseJoinColumnContainerAdapter(); + protected final JavaJoinColumn.Owner inverseJoinColumnOwner; + + protected JavaJoinColumn defaultInverseJoinColumn; + + + public GenericJavaJoinTable(JavaJoinTableRelationshipStrategy parent, Owner owner) { + super(parent, owner); + this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner(); + this.initializeSpecifiedInverseJoinColumns(); + } + + @Override + protected JavaJoinColumn.Owner buildJoinColumnOwner() { + return new JoinColumnOwner(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedInverseJoinColumns(); + if (this.defaultInverseJoinColumn != null) { + this.defaultInverseJoinColumn.synchronizeWithResourceModel(); + } + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedInverseJoinColumns()); + this.updateDefaultInverseJoinColumn(); + } + + + // ********** table annotation ********** + + @Override + public JoinTableAnnotation getTableAnnotation() { + return this.getRelationshipStrategy().getJoinTableAnnotation(); + } + + @Override + protected void removeTableAnnotation() { + // we don't remove a join table annotation when it is empty + } + + + // ********** inverse join columns ********** + + public ListIterator<JavaJoinColumn> inverseJoinColumns() { + return this.getInverseJoinColumns().iterator(); + } + + protected ListIterable<JavaJoinColumn> getInverseJoinColumns() { + return this.hasSpecifiedInverseJoinColumns() ? this.getSpecifiedInverseJoinColumns() : this.getDefaultInverseJoinColumns(); + } + + public int inverseJoinColumnsSize() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumnsSize() : this.defaultInverseJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedInverseJoinColumn() { + MappingTools.convertJoinTableDefaultToSpecifiedInverseJoinColumn(this); + } + + + // ********** specified inverse join columns ********** + + public ListIterator<JavaJoinColumn> specifiedInverseJoinColumns() { + return this.getSpecifiedInverseJoinColumns().iterator(); + } + + public ListIterable<JavaJoinColumn> getSpecifiedInverseJoinColumns() { + return new LiveCloneListIterable<JavaJoinColumn>(this.specifiedInverseJoinColumns); + } + + public int specifiedInverseJoinColumnsSize() { + return this.specifiedInverseJoinColumns.size(); + } + + public boolean hasSpecifiedInverseJoinColumns() { + return this.specifiedInverseJoinColumns.size() != 0; + } + + public JavaJoinColumn getSpecifiedInverseJoinColumn(int index) { + return this.specifiedInverseJoinColumns.get(index); + } + + public JavaJoinColumn addSpecifiedInverseJoinColumn() { + return this.addSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.size()); + } + + public JavaJoinColumn addSpecifiedInverseJoinColumn(int index) { + JoinColumnAnnotation annotation = this.getTableAnnotation().addInverseJoinColumn(index); + return this.addSpecifiedInverseJoinColumn_(index, annotation); + } + + public void removeSpecifiedInverseJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedInverseJoinColumn(int index) { + this.getTableAnnotation().removeInverseJoinColumn(index); + this.removeTableAnnotationIfUnset(); + this.removeSpecifiedInverseJoinColumn_(index); + } + + protected void removeSpecifiedInverseJoinColumn_(int index) { + this.removeItemFromList(index, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedInverseJoinColumn(int targetIndex, int sourceIndex) { + this.getTableAnnotation().moveInverseJoinColumn(targetIndex, sourceIndex); + this.moveItemInList(targetIndex, sourceIndex, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + public void clearSpecifiedInverseJoinColumns() { + // for now, we have to remove annotations one at a time... + for (int i = this.specifiedInverseJoinColumns.size(); i-- > 0; ) { + this.removeSpecifiedInverseJoinColumn(i); + } + } + + protected void initializeSpecifiedInverseJoinColumns() { + for (JoinColumnAnnotation joinColumnAnnotation : this.getInverseJoinColumnAnnotations()) { + this.specifiedInverseJoinColumns.add(this.buildInverseJoinColumn(joinColumnAnnotation)); + } + } + + protected void syncSpecifiedInverseJoinColumns() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedInverseJoinColumnContainerAdapter); + } + + protected Iterable<JoinColumnAnnotation> getInverseJoinColumnAnnotations() { + return CollectionTools.iterable(this.getTableAnnotation().inverseJoinColumns()); + } + + protected void moveSpecifiedInverseJoinColumn_(int index, JavaJoinColumn joinColumn) { + this.moveItemInList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + protected JavaJoinColumn addSpecifiedInverseJoinColumn_(int index, JoinColumnAnnotation joinColumnAnnotation) { + JavaJoinColumn joinColumn = this.buildInverseJoinColumn(joinColumnAnnotation); + this.addItemToList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + return joinColumn; + } + + protected void removeSpecifiedInverseJoinColumn_(JavaJoinColumn joinColumn) { + this.removeSpecifiedInverseJoinColumn_(this.specifiedInverseJoinColumns.indexOf(joinColumn)); + } + + /** + * specified inverse join column container adapter + */ + protected class SpecifiedInverseJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<JavaJoinColumn, JoinColumnAnnotation> + { + public Iterable<JavaJoinColumn> getContextElements() { + return GenericJavaJoinTable.this.getSpecifiedInverseJoinColumns(); + } + public Iterable<JoinColumnAnnotation> getResourceElements() { + return GenericJavaJoinTable.this.getInverseJoinColumnAnnotations(); + } + public JoinColumnAnnotation getResourceElement(JavaJoinColumn contextElement) { + return contextElement.getColumnAnnotation(); + } + public void moveContextElement(int index, JavaJoinColumn element) { + GenericJavaJoinTable.this.moveSpecifiedInverseJoinColumn_(index, element); + } + public void addContextElement(int index, JoinColumnAnnotation resourceElement) { + GenericJavaJoinTable.this.addSpecifiedInverseJoinColumn_(index, resourceElement); + } + public void removeContextElement(JavaJoinColumn element) { + GenericJavaJoinTable.this.removeSpecifiedInverseJoinColumn_(element); + } + } + + protected JavaJoinColumn.Owner buildInverseJoinColumnOwner() { + return new InverseJoinColumnOwner(); + } + + + // ********** default inverse join column ********** + + public JavaJoinColumn getDefaultInverseJoinColumn() { + return this.defaultInverseJoinColumn; + } + + protected void setDefaultInverseJoinColumn(JavaJoinColumn joinColumn) { + JavaJoinColumn old = this.defaultInverseJoinColumn; + this.defaultInverseJoinColumn = joinColumn; + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, old, joinColumn); + } + + protected ListIterable<JavaJoinColumn> getDefaultInverseJoinColumns() { + return (this.defaultInverseJoinColumn != null) ? + new SingleElementListIterable<JavaJoinColumn>(this.defaultInverseJoinColumn) : + EmptyListIterable.<JavaJoinColumn>instance(); + } + + protected int defaultInverseJoinColumnsSize() { + return (this.defaultInverseJoinColumn == null) ? 0 : 1; + } + + protected void updateDefaultInverseJoinColumn() { + if (this.buildsDefaultInverseJoinColumn()) { + if (this.defaultInverseJoinColumn == null) { + this.setDefaultInverseJoinColumn(this.buildInverseJoinColumn(new NullJoinColumnAnnotation(this.getTableAnnotation()))); + } else { + this.defaultInverseJoinColumn.update(); + } + } else { + this.setDefaultInverseJoinColumn(null); + } + } + + protected boolean buildsDefaultInverseJoinColumn() { + return ! this.hasSpecifiedInverseJoinColumns(); + } + + + // ********** misc ********** + + @Override + public JavaJoinTableRelationshipStrategy getParent() { + return (JavaJoinTableRelationshipStrategy) super.getParent(); + } + + protected JavaJoinTableRelationshipStrategy getRelationshipStrategy() { + return this.getParent(); + } + + @Override + protected String buildDefaultName() { + return this.getRelationshipStrategy().getJoinTableDefaultName(); + } + + public void initializeFrom(ReadOnlyJoinTable oldTable) { + super.initializeFrom(oldTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(oldTable.specifiedInverseJoinColumns())) { + this.addSpecifiedInverseJoinColumn().initializeFrom(joinColumn); + } + } + + public void initializeFromVirtual(ReadOnlyJoinTable virtualTable) { + super.initializeFromVirtual(virtualTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(virtualTable.inverseJoinColumns())) { + this.addSpecifiedInverseJoinColumn().initializeFromVirtual(joinColumn); + } + } + + protected JavaJoinColumn buildInverseJoinColumn(JoinColumnAnnotation joinColumnAnnotation) { + return this.buildJoinColumn(this.inverseJoinColumnOwner, joinColumnAnnotation); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getRelationshipStrategy().getRelationship().getMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return this.getRelationshipMapping().getPersistentAttribute(); + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaJoinColumn column : CollectionTools.iterable(this.inverseJoinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + // ********** validation ********** + + @Override + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validateJoinColumns(messages, reporter, astRoot); + this.validateJoinColumns(this.inverseJoinColumns(), messages, reporter, astRoot); + } + + public boolean validatesAgainstDatabase() { + return this.getRelationshipStrategy().validatesAgainstDatabase(); + } + + + // ********** join column owners ********** + + /** + * just a little common behavior + */ + protected abstract class AbstractJoinColumnOwner + implements JavaJoinColumn.Owner + { + protected AbstractJoinColumnOwner() { + super(); + } + + public TypeMapping getTypeMapping() { + return GenericJavaJoinTable.this.getRelationshipStrategy().getRelationship().getTypeMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return GenericJavaJoinTable.this.getPersistentAttribute(); + } + + /** + * @see MappingTools#buildJoinColumnDefaultName(org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn, org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn.Owner) + */ + public String getDefaultColumnName() { + throw new UnsupportedOperationException(); + } + + /** + * If there is a specified table name it needs to be the same + * the default table name. the table is always the join table + */ + public boolean tableNameIsInvalid(String tableName) { + return Tools.valuesAreDifferent(this.getDefaultTableName(), tableName); + } + + /** + * the join column can only be on the join table itself + */ + public Iterator<String> candidateTableNames() { + return EmptyIterator.instance(); + } + + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + return Tools.valuesAreEqual(GenericJavaJoinTable.this.getName(), tableName) ? + GenericJavaJoinTable.this.getDbTable() : + null; + } + + /** + * by default, the join column is, obviously, in the join table; + * not sure whether it can be anywhere else... + */ + public String getDefaultTableName() { + return GenericJavaJoinTable.this.getName(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaJoinTable.this.getValidationTextRange(astRoot); + } + } + + + /** + * 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 GenericJavaJoinTable.this.getRelationshipStrategy().getRelationship().getEntity(); + } + + public String getAttributeName() { + return MappingTools.getTargetAttributeName(GenericJavaJoinTable.this.getRelationshipMapping()); + } + + public org.eclipse.jpt.jpa.db.Table getReferencedColumnDbTable() { + return this.getTypeMapping().getPrimaryDbTable(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericJavaJoinTable.this.defaultJoinColumn == joinColumn; + } + + public int joinColumnsSize() { + return GenericJavaJoinTable.this.joinColumnsSize(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return GenericJavaJoinTable.this.getParent().buildJoinTableJoinColumnValidator((JoinColumn) column, this, (JoinColumnTextRangeResolver) textRangeResolver); + } + } + + + /** + * 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 = GenericJavaJoinTable.this.getRelationshipMapping(); + return (relationshipMapping == null) ? null : relationshipMapping.getResolvedTargetEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericJavaJoinTable.this.getRelationshipMapping(); + return (relationshipMapping == null) ? null : relationshipMapping.getName(); + } + + public org.eclipse.jpt.jpa.db.Table getReferencedColumnDbTable() { + Entity relationshipTarget = this.getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.getPrimaryDbTable(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericJavaJoinTable.this.defaultInverseJoinColumn == joinColumn; + } + + public int joinColumnsSize() { + return GenericJavaJoinTable.this.inverseJoinColumnsSize(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return GenericJavaJoinTable.this.getParent().buildJoinTableInverseJoinColumnValidator((JoinColumn) column, this, (JoinColumnTextRangeResolver) textRangeResolver); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaLobConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaLobConverter.java new file mode 100644 index 0000000000..9ccb2d3b51 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaLobConverter.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.LobConverter; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaLobConverter; +import org.eclipse.jpt.jpa.core.resource.java.LobAnnotation; + +public class GenericJavaLobConverter + extends AbstractJavaConverter + implements JavaLobConverter +{ + protected final LobAnnotation lobAnnotation; + + public GenericJavaLobConverter(JavaAttributeMapping parent, LobAnnotation lobAnnotation) { + super(parent); + this.lobAnnotation = lobAnnotation; + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return LobConverter.class; + } + + @Override + protected String getAnnotationName() { + return LobAnnotation.ANNOTATION_NAME; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.lobAnnotation.getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java new file mode 100644 index 0000000000..935834c6d3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToManyMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaManyToManyMapping; + +public class GenericJavaManyToManyMapping + extends AbstractJavaManyToManyMapping +{ + public GenericJavaManyToManyMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java new file mode 100644 index 0000000000..4cdc288501 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaManyToOneMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaManyToOneMapping; + +public class GenericJavaManyToOneMapping + extends AbstractJavaManyToOneMapping +{ + public GenericJavaManyToOneMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java new file mode 100644 index 0000000000..36d734b5b4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappedSuperclass.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaMappedSuperclass; +import org.eclipse.jpt.jpa.core.resource.java.MappedSuperclassAnnotation; + +/** + * Java mapped superclass + */ +public class GenericJavaMappedSuperclass + extends AbstractJavaMappedSuperclass +{ + public GenericJavaMappedSuperclass(JavaPersistentType parent, MappedSuperclassAnnotation mappingAnnotation) { + super(parent, mappingAnnotation); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappingJoinTableRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappingJoinTableRelationshipStrategy.java new file mode 100644 index 0000000000..f411dfbf43 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaMappingJoinTableRelationshipStrategy.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.context.JoinColumn.Owner; +import org.eclipse.jpt.jpa.core.context.java.JavaMappingJoinTableRelationship; +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.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.InverseJoinColumnValidator; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinColumnValidator; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinTableTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinTableValidator; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation; + +public class GenericJavaMappingJoinTableRelationshipStrategy + extends AbstractJavaJoinTableRelationshipStrategy +{ + public GenericJavaMappingJoinTableRelationshipStrategy(JavaMappingJoinTableRelationship parent) { + super(parent); + } + + + // ********** join table annotation ********** + + public JoinTableAnnotation getJoinTableAnnotation() { + return (JoinTableAnnotation) this.getResourcePersistentAttribute().getNonNullAnnotation(JoinTableAnnotation.ANNOTATION_NAME); + } + + @Override + protected JoinTableAnnotation addJoinTableAnnotation() { + return (JoinTableAnnotation) this.getResourcePersistentAttribute().addAnnotation(JoinTableAnnotation.ANNOTATION_NAME); + } + + @Override + protected void removeJoinTableAnnotation() { + this.getResourcePersistentAttribute().removeAnnotation(JoinTableAnnotation.ANNOTATION_NAME); + } + + + // ********** misc ********** + + protected JavaResourcePersistentAttribute getResourcePersistentAttribute() { + return this.getRelationship().getMapping().getResourcePersistentAttribute(); + } + + @Override + public JavaMappingJoinTableRelationship getParent() { + return (JavaMappingJoinTableRelationship) super.getParent(); + } + + @Override + public JavaMappingJoinTableRelationship getRelationship() { + return this.getParent(); + } + + public boolean isOverridable() { + return this.getJpaPlatformVariation().isJoinTableOverridable(); + } + + + // ********** validation ********** + + public boolean validatesAgainstDatabase() { + return this.getRelationshipMapping().validatesAgainstDatabase(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.getRelationship().getValidationTextRange(astRoot); + } + + public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) { + return new JoinTableValidator((JoinTable) table, textRangeResolver); + } + + public JptValidator buildJoinTableJoinColumnValidator(JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return new JoinColumnValidator(column, owner, textRangeResolver, new JoinTableTableDescriptionProvider()); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return new InverseJoinColumnValidator(column, owner, textRangeResolver, new JoinTableTableDescriptionProvider()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java new file mode 100644 index 0000000000..feaee86f38 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedNativeQuery.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaNamedNativeQuery; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaQuery; +import org.eclipse.jpt.jpa.core.resource.java.NamedNativeQueryAnnotation; + +/** + * <code>orm.xml</code> named native query + */ +public class GenericJavaNamedNativeQuery + extends AbstractJavaQuery<NamedNativeQueryAnnotation> + implements JavaNamedNativeQuery +{ + protected String resultClass; + + protected String resultSetMapping; + + + public GenericJavaNamedNativeQuery(JavaJpaContextNode parent, NamedNativeQueryAnnotation queryAnnotation) { + super(parent, queryAnnotation); + this.resultClass = queryAnnotation.getResultClass(); + this.resultSetMapping = queryAnnotation.getResultSetMapping(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setResultClass_(this.queryAnnotation.getResultClass()); + this.setResultSetMapping_(this.queryAnnotation.getResultSetMapping()); + } + + + // ********** result class ********** + + public String getResultClass() { + return this.resultClass; + } + + public void setResultClass(String resultClass) { + this.queryAnnotation.setResultClass(resultClass); + this.setResultClass_(resultClass); + } + + protected void setResultClass_(String resultClass) { + String old = this.resultClass; + this.resultClass = resultClass; + this.firePropertyChanged(RESULT_CLASS_PROPERTY, old, resultClass); + } + + public char getResultClassEnclosingTypeSeparator() { + return '.'; + } + + + // ********** result set mapping ********** + + public String getResultSetMapping() { + return this.resultSetMapping; + } + + public void setResultSetMapping(String resultSetMapping) { + this.queryAnnotation.setResultSetMapping(resultSetMapping); + this.setResultSetMapping_(resultSetMapping); + } + + protected void setResultSetMapping_(String resultSetMapping) { + String old = this.resultSetMapping; + this.resultSetMapping = resultSetMapping; + this.firePropertyChanged(RESULT_SET_MAPPING_PROPERTY, old, resultSetMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java new file mode 100644 index 0000000000..8c22d994ed --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaNamedQuery; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaQuery; +import org.eclipse.jpt.jpa.core.resource.java.NamedQueryAnnotation; + +/** + * Java named query + */ +public class GenericJavaNamedQuery + extends AbstractJavaQuery<NamedQueryAnnotation> + implements JavaNamedQuery +{ + public GenericJavaNamedQuery(JavaJpaContextNode parent, NamedQueryAnnotation queryAnnotation) { + super(parent, queryAnnotation); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java new file mode 100644 index 0000000000..864603a34e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNullAttributeMapping.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaAttributeMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.jpa.core.resource.java.Annotation; + +/** + * null mapping used when an attribute's default mapping cannot be determined + */ +public class GenericJavaNullAttributeMapping + extends AbstractJavaAttributeMapping<Annotation> +{ + public GenericJavaNullAttributeMapping(JavaPersistentAttribute parent) { + super(parent); + } + + public String getKey() { + return MappingKeys.NULL_ATTRIBUTE_MAPPING_KEY; + } + + @Override + protected String getAnnotationName() { + return null; + } + + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java new file mode 100644 index 0000000000..bf84573cf3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToManyMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaOneToManyMapping; + +public class GenericJavaOneToManyMapping + extends AbstractJavaOneToManyMapping +{ + public GenericJavaOneToManyMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java new file mode 100644 index 0000000000..c2f6397a6c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOneToOneMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaOneToOneMapping; + +public class GenericJavaOneToOneMapping + extends AbstractJavaOneToOneMapping +{ + public GenericJavaOneToOneMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOrderable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOrderable.java new file mode 100644 index 0000000000..653657946e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOrderable.java @@ -0,0 +1,486 @@ +/******************************************************************************* + * 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.jpa1.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.jpa.core.context.NamedColumn; +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.JavaNamedColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +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.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.OrderColumnValidator; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.GenericJavaOrderColumn2_0; +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.OrderColumn2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrderColumn2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrderable2_0; +import org.eclipse.jpt.jpa.core.jpa2.resource.java.OrderColumn2_0Annotation; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.jpa.core.resource.java.OrderByAnnotation; +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 ordering + * <p> + * <strong>NB:</strong> Setting any flag to <code>false</code> (or setting the + * specified "order by" to <code>null</code>) can be a bit unpredictable. The + * intent is to set a flag to <code>true</code> (or set the specified "order by" + * to a non-<code>null</code> value). + * <p> + * <strong>(JPA 2.0 only) NB:</strong> If both the "order by" and the "order + * column" annotations are present (which is prohibited by the JPA spec), + * both are ignored. + */ +public class GenericJavaOrderable + extends AbstractJavaJpaContextNode + implements JavaOrderable2_0 +{ + protected String specifiedOrderBy; + protected boolean noOrdering = false; + protected boolean pkOrdering = false; + protected boolean customOrdering = false; + + // JPA 2.0 + protected final Owner owner; // this is null for JPA 1.0 mappings + protected boolean orderColumnOrdering = false; + protected final JavaOrderColumn2_0 orderColumn; + + + /** + * JPA 1.0 + */ + public GenericJavaOrderable(JavaAttributeMapping parent) { + this(parent, null); + } + + /** + * JPA 2.0 + */ + public GenericJavaOrderable(JavaAttributeMapping parent, Owner owner) { + super(parent); + this.specifiedOrderBy = this.buildSpecifiedOrderBy(); + this.noOrdering = this.buildNoOrdering(); + this.pkOrdering = this.buildPkOrdering(); + this.customOrdering = this.buildCustomOrdering(); + + this.owner = owner; + this.orderColumnOrdering = this.buildOrderColumnOrdering(); + this.orderColumn = this.buildOrderColumn(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + + this.setSpecifiedOrderBy_(this.buildSpecifiedOrderBy()); + this.setNoOrdering_(this.buildNoOrdering()); + this.setPkOrdering_(this.buildPkOrdering()); + this.setCustomOrdering_(this.buildCustomOrdering()); + + this.setOrderColumnOrdering_(this.buildOrderColumnOrdering()); + this.orderColumn.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.orderColumn.update(); + } + + + // ********** specified order by ********** + + public String getSpecifiedOrderBy() { + return this.specifiedOrderBy; + } + + public void setSpecifiedOrderBy(String orderBy) { + if (orderBy != null) { + this.removeOrderColumnAnnotation(); + this.getOrderByAnnotationForUpdate().setValue(orderBy); + + this.setSpecifiedOrderBy_(orderBy); + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(true); + this.setOrderColumnOrdering_(false); + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setSpecifiedOrderBy_(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected String buildSpecifiedOrderBy() { + if (this.orderColumnAnnotationIsPresent()) { + return null; + } + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + return (orderByAnnotation == null) ? null : orderByAnnotation.getValue(); + } + + + // ********** no ordering ********** + + public boolean isNoOrdering() { + return this.noOrdering; + } + + public void setNoOrdering(boolean noOrdering) { + if (noOrdering) { + this.removeOrderColumnAnnotation(); + if (this.getOrderByAnnotation() != null) { + this.removeOrderByAnnotation(); + } + + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(true); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + } else { + this.setPkOrdering(true); // hmmm... + } + } + + protected void setNoOrdering_(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + protected boolean buildNoOrdering() { + return this.isJpa2_0Compatible() ? this.buildNoOrdering2_0() : this.buildNoOrdering1_0(); + } + + /** + * both annotations are missing <em>or</em> both are present + */ + protected boolean buildNoOrdering2_0() { + boolean orderByMissing = (this.getOrderByAnnotation() == null); + boolean orderByPresent = ! orderByMissing; + boolean orderColumnMissing = (this.getOrderColumnAnnotation() == null); + boolean orderColumnPresent = ! orderColumnMissing; + return (orderByMissing && orderColumnMissing) || (orderByPresent && orderColumnPresent); + } + + /** + * the order-by annotation is missing + */ + protected boolean buildNoOrdering1_0() { + return this.getOrderByAnnotation() == null; + } + + + // ********** pk ordering ********** + + public boolean isPkOrdering() { + return this.pkOrdering; + } + + public void setPkOrdering(boolean pkOrdering) { + if (pkOrdering) { + this.removeOrderColumnAnnotation(); + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + if (orderByAnnotation == null) { + this.addOrderByAnnotation(); + } else { + orderByAnnotation.setValue(null); + } + + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(false); + this.setPkOrdering_(true); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setPkOrdering_(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + /** + * the order-by annotation is present but no value specified + */ + protected boolean buildPkOrdering() { + if (this.orderColumnAnnotationIsPresent()) { + return false; + } + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + return (orderByAnnotation != null) && (orderByAnnotation.getValue() == null); + } + + + // ********** custom ordering ********** + + public boolean isCustomOrdering() { + return this.customOrdering; + } + + public void setCustomOrdering(boolean customOrdering) { + if (customOrdering) { + this.setSpecifiedOrderBy(""); //$NON-NLS-1$ + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setCustomOrdering_(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + /** + * the order-by annotation is present and it has a specified value + */ + protected boolean buildCustomOrdering() { + if (this.orderColumnAnnotationIsPresent()) { + return false; + } + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + return (orderByAnnotation != null) && (orderByAnnotation.getValue() != null); + } + + + // ********** order column ordering ********** + + public boolean isOrderColumnOrdering() { + return this.orderColumnOrdering; + } + + public void setOrderColumnOrdering(boolean orderColumnOrdering) { + if (orderColumnOrdering) { + this.removeOrderByAnnotation(); + if (this.getOrderColumnAnnotation() == null) { + this.addOrderColumnAnnotation(); + } + + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(true); + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setOrderColumnOrdering_(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + /** + * JPA 2.0 only; + * the order column annotation is present <em>and</em> + * the order-by annotation is missing + */ + protected boolean buildOrderColumnOrdering() { + return this.orderColumnAnnotationIsPresent() && + (this.getOrderByAnnotation() == null); + } + + + // ********** order column ********** + + public JavaOrderColumn2_0 getOrderColumn() { + return this.orderColumn; + } + + protected JavaOrderColumn2_0 buildOrderColumn() { + JavaNamedColumn.Owner columnOwner = new OrderColumnOwner(); + return this.isJpa2_0Compatible() ? + this.getJpaFactory2_0().buildJavaOrderColumn(this, columnOwner) : + new GenericJavaOrderColumn2_0(this, columnOwner); + } + + + // ********** order by annotation ********** + + protected OrderByAnnotation getOrderByAnnotation() { + return (OrderByAnnotation) this.getResourcePersistentAttribute().getAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + protected OrderByAnnotation getOrderByAnnotationForUpdate() { + OrderByAnnotation annotation = this.getOrderByAnnotation(); + return (annotation != null) ? annotation : this.addOrderByAnnotation(); + } + + protected OrderByAnnotation addOrderByAnnotation() { + return (OrderByAnnotation) this.getResourcePersistentAttribute().addAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + protected void removeOrderByAnnotation() { + this.getResourcePersistentAttribute().removeAnnotation(OrderByAnnotation.ANNOTATION_NAME); + } + + + // ********** order column annotation ********** + + protected OrderColumn2_0Annotation getOrderColumnAnnotation() { + return (OrderColumn2_0Annotation) this.getResourcePersistentAttribute().getAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + /** + * NB: Only return <code>true</code> for JPA 2.0 mappings. + */ + protected boolean orderColumnAnnotationIsPresent() { + return this.isJpa2_0Compatible() && (this.getOrderColumnAnnotation() != null); + } + + protected OrderColumn2_0Annotation addOrderColumnAnnotation() { + return (OrderColumn2_0Annotation) this.getResourcePersistentAttribute().addAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + protected void removeOrderColumnAnnotation() { + if (this.orderColumnAnnotationIsPresent()) { + this.removeOrderColumnAnnotation_(); + } + } + + protected void removeOrderColumnAnnotation_() { + this.getResourcePersistentAttribute().removeAnnotation(OrderColumn2_0Annotation.ANNOTATION_NAME); + } + + + // ********** misc ********** + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + protected JavaAttributeMapping getAttributeMapping() { + return this.getParent(); + } + + protected JavaPersistentAttribute getPersistentAttribute() { + return this.getAttributeMapping().getPersistentAttribute(); + } + + public JavaResourcePersistentAttribute getResourcePersistentAttribute() { + return this.getPersistentAttribute().getResourcePersistentAttribute(); + } + + // JPA 2.0 only + public String getDefaultTableName() { + return this.owner.getTableName(); + } + + // JPA 2.0 only + protected Table resolveDbTable(String tableName) { + return this.owner.resolveDbTable(tableName); + } + + + // ********** 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.orderColumn.javaCompletionProposals(pos, filter, astRoot); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + TextRange textRange = this.getOrderByAnnotationTextRange(astRoot); + return (textRange != null) ? textRange : this.getAttributeMapping().getValidationTextRange(astRoot); + } + + protected TextRange getOrderByAnnotationTextRange(CompilationUnit astRoot) { + OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); + return (orderByAnnotation == null) ? null : orderByAnnotation.getTextRange(astRoot); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + if (this.orderColumnAnnotationIsPresent() && (this.getOrderByAnnotation() != null)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ORDER_COLUMN_AND_ORDER_BY_BOTH_SPECIFIED, + new String[] {this.getPersistentAttribute().getName()}, + this.getAttributeMapping(), + this.getOrderByAnnotationTextRange(astRoot) + ) + ); + } + if (this.orderColumnOrdering) { + //TODO validation message if type is not List + this.orderColumn.validate(messages, reporter, astRoot); + } + } + + + // ********** order column owner (JPA 2.0) ********** + + protected class OrderColumnOwner + implements JavaNamedColumn.Owner + { + public String getDefaultTableName() { + return GenericJavaOrderable.this.getDefaultTableName(); + } + + public Table resolveDbTable(String tableName) { + return GenericJavaOrderable.this.resolveDbTable(tableName); + } + + public String getDefaultColumnName() { + return this.getPersistentAttribute().getName() + "_ORDER"; //$NON-NLS-1$ + } + + public TypeMapping getTypeMapping() { + return this.getPersistentAttribute().getOwningTypeMapping(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaOrderable.this.getValidationTextRange(astRoot); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return new OrderColumnValidator((OrderColumn2_0) column, textRangeResolver); + } + + protected JavaPersistentAttribute getPersistentAttribute() { + return GenericJavaOrderable.this.getPersistentAttribute(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOverrideRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOverrideRelationship.java new file mode 100644 index 0000000000..e6804dbb4f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaOverrideRelationship.java @@ -0,0 +1,247 @@ +/******************************************************************************* + * 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.jpa1.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.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.MappedByRelationship; +import org.eclipse.jpt.jpa.core.context.OverrideRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyOverrideRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyRelationship; +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.JavaAssociationOverride; +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.JavaRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.context.java.GenericJavaOverrideJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.GenericJavaOverrideJoinTableRelationshipStrategy2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOverrideRelationship2_0; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericJavaOverrideRelationship + extends AbstractJavaJpaContextNode + implements JavaOverrideRelationship2_0 +{ + protected JavaRelationshipStrategy strategy; + + protected final JavaJoinColumnRelationshipStrategy joinColumnStrategy; + + // JPA 2.0 + protected final JavaJoinTableRelationshipStrategy joinTableStrategy; + + + public GenericJavaOverrideRelationship(JavaAssociationOverride parent) { + super(parent); + this.joinColumnStrategy = this.buildJoinColumnStrategy(); + this.joinTableStrategy = this.buildJoinTableStrategy(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.joinColumnStrategy.synchronizeWithResourceModel(); + this.joinTableStrategy.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.setStrategy(this.buildStrategy()); + this.joinColumnStrategy.update(); + this.joinTableStrategy.update(); + } + + + // ********** strategy ********** + + public JavaRelationshipStrategy getStrategy() { + return this.strategy; + } + + protected void setStrategy(JavaRelationshipStrategy strategy) { + JavaRelationshipStrategy old = this.strategy; + this.strategy = strategy; + this.firePropertyChanged(STRATEGY_PROPERTY, old, strategy); + } + + protected JavaRelationshipStrategy buildStrategy() { + if (this.isJpa2_0Compatible()) { + if (this.joinColumnStrategy.hasSpecifiedJoinColumns()) { + return this.joinColumnStrategy; + } + return this.joinTableStrategy; + } + return this.joinColumnStrategy; + } + + + // ********** join column strategy ********** + + public JavaJoinColumnRelationshipStrategy getJoinColumnStrategy() { + return this.joinColumnStrategy; + } + + public boolean strategyIsJoinColumn() { + return this.strategy == this.joinColumnStrategy; + } + + public void setStrategyToJoinColumn() { + this.joinColumnStrategy.addStrategy(); + this.joinTableStrategy.removeStrategy(); + } + + public boolean mayHaveDefaultJoinColumn() { + return false; + } + + protected JavaJoinColumnRelationshipStrategy buildJoinColumnStrategy() { + return new GenericJavaOverrideJoinColumnRelationshipStrategy(this); + } + + + // ********** join table strategy ********** + + public JavaJoinTableRelationshipStrategy getJoinTableStrategy() { + return this.joinTableStrategy; + } + + public boolean strategyIsJoinTable() { + return this.strategy == this.joinTableStrategy; + } + + public void setStrategyToJoinTable() { + this.joinTableStrategy.addStrategy(); + this.joinColumnStrategy.removeStrategy(); + } + + public boolean mayHaveDefaultJoinTable() { + return this.isVirtual() && this.strategyIsJoinTable(); + } + + protected JavaJoinTableRelationshipStrategy buildJoinTableStrategy() { + return this.isJpa2_0Compatible() ? + new GenericJavaOverrideJoinTableRelationshipStrategy2_0(this) : + new NullJavaJoinTableRelationshipStrategy(this); + } + + + // ********** conversions ********** + + public void initializeFrom(ReadOnlyRelationship oldRelationship) { + oldRelationship.initializeOn(this); + } + + public void initializeOn(Relationship newRelationship) { + newRelationship.initializeFromJoinTableRelationship(this); + newRelationship.initializeFromJoinColumnRelationship(this); + } + + public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) { + // NOP + } + + public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) { + this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy()); + } + + public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) { + this.joinColumnStrategy.initializeFrom(oldRelationship.getJoinColumnStrategy()); + } + + public void initializeFromVirtual(ReadOnlyOverrideRelationship virtualRelationship) { + virtualRelationship.initializeOnSpecified(this); + } + + public void initializeOnSpecified(OverrideRelationship specifiedRelationship) { + throw new UnsupportedOperationException(); + } + + public void initializeFromVirtualJoinTableRelationship(ReadOnlyJoinTableRelationship virtualRelationship) { + this.joinTableStrategy.initializeFromVirtual(virtualRelationship.getJoinTableStrategy()); + } + + public void initializeFromVirtualJoinColumnRelationship(ReadOnlyJoinColumnRelationship virtualRelationship) { + this.joinColumnStrategy.initializeFromVirtual(virtualRelationship.getJoinColumnStrategy()); + } + + + // ********** misc ********** + + @Override + public JavaAssociationOverride getParent() { + return (JavaAssociationOverride) super.getParent(); + } + + public JavaAssociationOverride getAssociationOverride() { + return this.getParent(); + } + + public TypeMapping getTypeMapping() { + return this.getAssociationOverride().getContainer().getTypeMapping(); + } + + public Entity getEntity() { + TypeMapping typeMapping = this.getTypeMapping(); + return (typeMapping instanceof Entity) ? (Entity) typeMapping : null; + } + + public boolean isVirtual() { + return false; + } + + public RelationshipMapping getMapping() { + return this.getAssociationOverride().getMapping(); + } + + + // ********** 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 ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.getAssociationOverride().getValidationTextRange(astRoot); + } + + @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/jpa1/context/java/GenericJavaPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPersistentAttribute.java new file mode 100644 index 0000000000..21dd9cd90e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPersistentAttribute.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.jpa.core.context.AccessType; +import org.eclipse.jpt.jpa.core.context.PersistentType; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericPersistentAttributeValidator; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; + +/** + * Generic Java persistent attribute + */ +public class GenericJavaPersistentAttribute + extends AbstractJavaPersistentAttribute +{ + + public GenericJavaPersistentAttribute(PersistentType parent, JavaResourcePersistentAttribute jrpa) { + super(parent, jrpa); + } + + + // ********** access ********** + + /** + * JPA 1.0 does not support specified access, so we return <code>null</code>. + */ + @Override + public AccessType getSpecifiedAccess() { + return null; + } + + public void setSpecifiedAccess(AccessType access) { + throw new UnsupportedOperationException(); + } + + // ********** validation ********** + + @Override + protected JptValidator buildAttibuteValidator(CompilationUnit astRoot) { + return new GenericPersistentAttributeValidator(this, this, buildTextRangeResolver(astRoot)); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPersistentType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPersistentType.java new file mode 100644 index 0000000000..b66d1aecf2 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPersistentType.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.AccessType; +import org.eclipse.jpt.jpa.core.context.PersistentType; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaPersistentType; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; + +/** + * JPA 1.0 Java persistent type. + * The specified access is always null. + */ +public class GenericJavaPersistentType + extends AbstractJavaPersistentType +{ + public GenericJavaPersistentType(PersistentType.Owner parent, JavaResourcePersistentType jrpt) { + super(parent, jrpt); + } + + + // ********** access ********** + + /** + * Return <code>null</code> - JPA 1.0 does not support a specified access. + */ + @Override + protected AccessType buildSpecifiedAccess() { + return null; + } + + /** + * JPA 1.0 does not support a specified access. + */ + public void setSpecifiedAccess(AccessType specifiedAccess) { + throw new UnsupportedOperationException(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..8e5c92d5c4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaPrimaryKeyJoinColumn.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.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.iterables.EmptyIterable; +import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable; +import org.eclipse.jpt.jpa.core.context.java.JavaBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaNamedColumn; +import org.eclipse.jpt.jpa.core.internal.context.java.JavaPrimaryKeyJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.jpa.db.Column; +import org.eclipse.jpt.jpa.db.Table; + +/** + * Java primary key join column + */ +public class GenericJavaPrimaryKeyJoinColumn + extends AbstractJavaNamedColumn<PrimaryKeyJoinColumnAnnotation, JavaBaseJoinColumn.Owner> + implements JavaPrimaryKeyJoinColumn +{ + /** @see AbstractJavaNamedColumn#AbstractJavaNamedColumn(org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode, org.eclipse.jpt.jpa.core.context.java.JavaNamedColumn.Owner, org.eclipse.jpt.jpa.core.resource.java.NamedColumnAnnotation) */ + protected /* final */ PrimaryKeyJoinColumnAnnotation columnAnnotation; // never null + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericJavaPrimaryKeyJoinColumn(JavaJpaContextNode parent, JavaBaseJoinColumn.Owner owner, PrimaryKeyJoinColumnAnnotation columnAnnotation) { + super(parent, owner, columnAnnotation); + this.specifiedReferencedColumnName = this.buildSpecifiedReferencedColumnName(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedReferencedColumnName_(this.buildSpecifiedReferencedColumnName()); + } + + @Override + public void update() { + super.update(); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** column annotation ********** + + @Override + public PrimaryKeyJoinColumnAnnotation getColumnAnnotation() { + return this.columnAnnotation; + } + + @Override + protected void setColumnAnnotation(PrimaryKeyJoinColumnAnnotation columnAnnotation) { + this.columnAnnotation = columnAnnotation; + } + + @Override + protected void removeColumnAnnotation() { + // we don't remove a pk join column annotation when it is empty + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String name) { + if (this.valuesAreDifferent(this.specifiedReferencedColumnName, name)) { + this.columnAnnotation.setReferencedColumnName(name); + this.removeColumnAnnotationIfUnset(); + this.setSpecifiedReferencedColumnName_(name); + } + } + + protected void setSpecifiedReferencedColumnName_(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return this.columnAnnotation.getReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + // TODO not correct when we start supporting + // primary key join columns in 1-1 mappings + protected String buildDefaultReferencedColumnName() { + return this.buildDefaultName(); + } + + + // ********** database stuff ********** + + public Table getReferencedColumnDbTable() { + return this.owner.getReferencedColumnDbTable(); + } + + protected Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public boolean referencedColumnIsResolved() { + return this.getReferencedDbColumn() != null; + } + + + // ********** misc ********** + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + @Override + public String getTable() { + return this.owner.getDefaultTableName(); + } + + + // ********** 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.referencedColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateReferencedColumnNames(filter).iterator(); + } + return null; + } + + public boolean referencedColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.columnAnnotation.referencedColumnNameTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateReferencedColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateReferencedColumnNames(filter)); + } + + protected Iterable<String> getCandidateReferencedColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateReferencedColumnNames(), filter); + } + + protected Iterable<String> getCandidateReferencedColumnNames() { + Table table = this.owner.getReferencedColumnDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + + // ********** validation ********** + + @Override + protected NamedColumnTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) { + return new JavaPrimaryKeyJoinColumnTextRangeResolver(this, astRoot); + } + + public TextRange getReferencedColumnNameTextRange(CompilationUnit astRoot) { + TextRange textRange = this.columnAnnotation.getReferencedColumnNameTextRange(astRoot); + return textRange != null ? textRange : this.getValidationTextRange(astRoot); + } + + + // ********** misc ********** + + @Override + public void toString(StringBuilder sb) { + super.toString(sb); + sb.append("=>"); //$NON-NLS-1$ + sb.append(this.getReferencedColumnName()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java new file mode 100644 index 0000000000..220db7e932 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java @@ -0,0 +1,370 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.ArrayList; +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.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.StringTools; +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.SubIterableWrapper; +import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator; +import org.eclipse.jpt.jpa.core.context.NamedNativeQuery; +import org.eclipse.jpt.jpa.core.context.NamedQuery; +import org.eclipse.jpt.jpa.core.context.Query; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaNamedNativeQuery; +import org.eclipse.jpt.jpa.core.context.java.JavaNamedQuery; +import org.eclipse.jpt.jpa.core.context.java.JavaQuery; +import org.eclipse.jpt.jpa.core.context.java.JavaQueryContainer; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +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.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.NestableAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java query container + */ +public class GenericJavaQueryContainer + extends AbstractJavaJpaContextNode + implements JavaQueryContainer +{ + protected final Owner owner; + + protected final Vector<JavaNamedQuery> namedQueries = new Vector<JavaNamedQuery>(); + protected NamedQueryContainerAdapter namedQueryContainerAdapter = new NamedQueryContainerAdapter(); + + protected final Vector<JavaNamedNativeQuery> namedNativeQueries = new Vector<JavaNamedNativeQuery>(); + protected NamedNativeQueryContainerAdapter namedNativeQueryContainerAdapter = new NamedNativeQueryContainerAdapter(); + + + public GenericJavaQueryContainer(JavaJpaContextNode parent, Owner owner) { + super(parent); + this.owner = owner; + this.initializeNamedQueries(); + this.initializeNamedNativeQueries(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncNamedQueries(); + this.syncNamedNativeQueries(); + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getNamedQueries()); + this.updateNodes(this.getNamedNativeQueries()); + } + + + // ********** named queries ********** + + public ListIterator<JavaNamedQuery> namedQueries() { + return this.getNamedQueries().iterator(); + } + + protected ListIterable<JavaNamedQuery> getNamedQueries() { + return new LiveCloneListIterable<JavaNamedQuery>(this.namedQueries); + } + + public int namedQueriesSize() { + return this.namedQueries.size(); + } + + public JavaNamedQuery addNamedQuery() { + return this.addNamedQuery(this.namedQueries.size()); + } + + public JavaNamedQuery addNamedQuery(int index) { + NamedQueryAnnotation annotation = this.buildNamedQueryAnnotation(index); + return this.addNamedQuery_(index, annotation); + } + + protected NamedQueryAnnotation buildNamedQueryAnnotation(int index) { + return (NamedQueryAnnotation) this.owner.getResourceAnnotatedElement().addAnnotation(index, NamedQueryAnnotation.ANNOTATION_NAME, NamedQueriesAnnotation.ANNOTATION_NAME); + } + + public void removeNamedQuery(NamedQuery namedQuery) { + this.removeNamedQuery(this.namedQueries.indexOf(namedQuery)); + } + + public void removeNamedQuery(int index) { + this.owner.getResourceAnnotatedElement().removeAnnotation(index, NamedQueryAnnotation.ANNOTATION_NAME, NamedQueriesAnnotation.ANNOTATION_NAME); + this.removeNamedQuery_(index); + } + + protected void removeNamedQuery_(int index) { + this.removeItemFromList(index, this.namedQueries, NAMED_QUERIES_LIST); + } + + public void moveNamedQuery(int targetIndex, int sourceIndex) { + this.owner.getResourceAnnotatedElement().moveAnnotation(targetIndex, sourceIndex, NamedQueriesAnnotation.ANNOTATION_NAME); + this.moveItemInList(targetIndex, sourceIndex, this.namedQueries, NAMED_QUERIES_LIST); + } + + protected void initializeNamedQueries() { + for (NamedQueryAnnotation annotation : this.getNamedQueryAnnotations()) { + this.namedQueries.add(this.buildNamedQuery(annotation)); + } + } + + protected JavaNamedQuery buildNamedQuery(NamedQueryAnnotation namedQueryAnnotation) { + return this.getJpaFactory().buildJavaNamedQuery(this, namedQueryAnnotation); + } + + protected void syncNamedQueries() { + ContextContainerTools.synchronizeWithResourceModel(this.namedQueryContainerAdapter); + } + + protected Iterable<NamedQueryAnnotation> getNamedQueryAnnotations() { + return new SubIterableWrapper<NestableAnnotation, NamedQueryAnnotation>( + CollectionTools.iterable(this.namedQueryAnnotations()) + ); + } + + protected Iterator<NestableAnnotation> namedQueryAnnotations() { + return this.owner.getResourceAnnotatedElement().annotations(NamedQueryAnnotation.ANNOTATION_NAME, NamedQueriesAnnotation.ANNOTATION_NAME); + } + + protected void moveNamedQuery_(int index, JavaNamedQuery namedQuery) { + this.moveItemInList(index, namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + protected JavaNamedQuery addNamedQuery_(int index, NamedQueryAnnotation namedQueryAnnotation) { + JavaNamedQuery query = this.buildNamedQuery(namedQueryAnnotation); + this.addItemToList(index, query, this.namedQueries, NAMED_QUERIES_LIST); + return query; + } + + protected void removeNamedQuery_(JavaNamedQuery namedQuery) { + this.removeNamedQuery_(this.namedQueries.indexOf(namedQuery)); + } + + /** + * named query container adapter + */ + protected class NamedQueryContainerAdapter + implements ContextContainerTools.Adapter<JavaNamedQuery, NamedQueryAnnotation> + { + public Iterable<JavaNamedQuery> getContextElements() { + return GenericJavaQueryContainer.this.getNamedQueries(); + } + public Iterable<NamedQueryAnnotation> getResourceElements() { + return GenericJavaQueryContainer.this.getNamedQueryAnnotations(); + } + public NamedQueryAnnotation getResourceElement(JavaNamedQuery contextElement) { + return contextElement.getQueryAnnotation(); + } + public void moveContextElement(int index, JavaNamedQuery element) { + GenericJavaQueryContainer.this.moveNamedQuery_(index, element); + } + public void addContextElement(int index, NamedQueryAnnotation resourceElement) { + GenericJavaQueryContainer.this.addNamedQuery_(index, resourceElement); + } + public void removeContextElement(JavaNamedQuery element) { + GenericJavaQueryContainer.this.removeNamedQuery_(element); + } + } + + + // ********** named native queries ********** + + public ListIterator<JavaNamedNativeQuery> namedNativeQueries() { + return this.getNamedNativeQueries().iterator(); + } + + protected ListIterable<JavaNamedNativeQuery> getNamedNativeQueries() { + return new LiveCloneListIterable<JavaNamedNativeQuery>(this.namedNativeQueries); + } + + public int namedNativeQueriesSize() { + return this.namedNativeQueries.size(); + } + + public JavaNamedNativeQuery addNamedNativeQuery() { + return this.addNamedNativeQuery(this.namedNativeQueries.size()); + } + + public JavaNamedNativeQuery addNamedNativeQuery(int index) { + NamedNativeQueryAnnotation annotation = this.buildNamedNativeQueryAnnotation(index); + return this.addNamedNativeQuery_(index, annotation); + } + + protected NamedNativeQueryAnnotation buildNamedNativeQueryAnnotation(int index) { + return (NamedNativeQueryAnnotation) this.owner.getResourceAnnotatedElement().addAnnotation(index, NamedNativeQueryAnnotation.ANNOTATION_NAME, NamedNativeQueriesAnnotation.ANNOTATION_NAME); + } + + public void removeNamedNativeQuery(NamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + public void removeNamedNativeQuery(int index) { + this.owner.getResourceAnnotatedElement().removeAnnotation(index, NamedNativeQueryAnnotation.ANNOTATION_NAME, NamedNativeQueriesAnnotation.ANNOTATION_NAME); + this.removeNamedNativeQuery_(index); + } + + protected void removeNamedNativeQuery_(int index) { + this.removeItemFromList(index, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + public void moveNamedNativeQuery(int targetIndex, int sourceIndex) { + this.owner.getResourceAnnotatedElement().moveAnnotation(targetIndex, sourceIndex, NamedNativeQueriesAnnotation.ANNOTATION_NAME); + this.moveItemInList(targetIndex, sourceIndex, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + protected void initializeNamedNativeQueries() { + for (NamedNativeQueryAnnotation annotation : this.getNamedNativeQueryAnnotations()) { + this.namedNativeQueries.add(this.buildNamedNativeQuery(annotation)); + } + } + + protected JavaNamedNativeQuery buildNamedNativeQuery(NamedNativeQueryAnnotation namedNativeQueryAnnotation) { + return this.getJpaFactory().buildJavaNamedNativeQuery(this, namedNativeQueryAnnotation); + } + + protected void syncNamedNativeQueries() { + ContextContainerTools.synchronizeWithResourceModel(this.namedNativeQueryContainerAdapter); + } + + protected Iterable<NamedNativeQueryAnnotation> getNamedNativeQueryAnnotations() { + return new SubIterableWrapper<NestableAnnotation, NamedNativeQueryAnnotation>( + CollectionTools.iterable(this.namedNativeQueryAnnotations()) + ); + } + + protected Iterator<NestableAnnotation> namedNativeQueryAnnotations() { + return this.owner.getResourceAnnotatedElement().annotations(NamedNativeQueryAnnotation.ANNOTATION_NAME, NamedNativeQueriesAnnotation.ANNOTATION_NAME); + } + + protected void moveNamedNativeQuery_(int index, JavaNamedNativeQuery namedNativeQuery) { + this.moveItemInList(index, namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + protected JavaNamedNativeQuery addNamedNativeQuery_(int index, NamedNativeQueryAnnotation namedNativeQueryAnnotation) { + JavaNamedNativeQuery query = this.buildNamedNativeQuery(namedNativeQueryAnnotation); + this.addItemToList(index, query, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + return query; + } + + protected void removeNamedNativeQuery_(JavaNamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery_(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + /** + * named native query container adapter + */ + protected class NamedNativeQueryContainerAdapter + implements ContextContainerTools.Adapter<JavaNamedNativeQuery, NamedNativeQueryAnnotation> + { + public Iterable<JavaNamedNativeQuery> getContextElements() { + return GenericJavaQueryContainer.this.getNamedNativeQueries(); + } + public Iterable<NamedNativeQueryAnnotation> getResourceElements() { + return GenericJavaQueryContainer.this.getNamedNativeQueryAnnotations(); + } + public NamedNativeQueryAnnotation getResourceElement(JavaNamedNativeQuery contextElement) { + return contextElement.getQueryAnnotation(); + } + public void moveContextElement(int index, JavaNamedNativeQuery element) { + GenericJavaQueryContainer.this.moveNamedNativeQuery_(index, element); + } + public void addContextElement(int index, NamedNativeQueryAnnotation resourceElement) { + GenericJavaQueryContainer.this.addNamedNativeQuery_(index, resourceElement); + } + public void removeContextElement(JavaNamedNativeQuery element) { + GenericJavaQueryContainer.this.removeNamedNativeQuery_(element); + } + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + super.validate(messages, reporter, astRoot); + this.validateQueries(messages, astRoot); + } + + protected void validateQueries(List<IMessage> messages, CompilationUnit astRoot) { + for (Iterator<JavaQuery> localQueries = this.queries(); localQueries.hasNext(); ) { + JavaQuery localQuery = localQueries.next(); + String name = localQuery.getName(); + if (StringTools.stringIsEmpty(name)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_NAME_UNDEFINED, + new String[] {}, + localQuery, + localQuery.getNameTextRange(astRoot) + ) + ); + } else { + List<String> reportedNames = new ArrayList<String>(); + for (Iterator<Query> globalQueries = this.getPersistenceUnit().queries(); globalQueries.hasNext(); ) { + if (localQuery.duplicates(globalQueries.next()) && !reportedNames.contains(name)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_DUPLICATE_NAME, + new String[] {name}, + localQuery, + localQuery.getNameTextRange(astRoot) + ) + ); + reportedNames.add(name); + } + } + } + String query = localQuery.getQuery(); + if (StringTools.stringIsEmpty(query)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_STATEMENT_UNDEFINED, + new String[] {name}, + localQuery, + localQuery.getNameTextRange(astRoot) + ) + ); + } + } + } + + + @SuppressWarnings("unchecked") + public Iterator<JavaQuery> queries() { + return new CompositeIterator<JavaQuery>(this.namedNativeQueries(), this.namedQueries()); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.owner.getResourceAnnotatedElement().getTextRange(astRoot); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryHint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryHint.java new file mode 100644 index 0000000000..ee05688b83 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryHint.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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.jpa1.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.JavaQuery; +import org.eclipse.jpt.jpa.core.context.java.JavaQueryHint; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.resource.java.QueryHintAnnotation; + +/** + * Java query hing + */ +public class GenericJavaQueryHint + extends AbstractJavaJpaContextNode + implements JavaQueryHint +{ + protected final QueryHintAnnotation queryHintAnnotation; + + protected String name; + protected String value; + + + public GenericJavaQueryHint(JavaQuery parent, QueryHintAnnotation queryHintAnnotation) { + super(parent); + this.queryHintAnnotation = queryHintAnnotation; + this.name = queryHintAnnotation.getName(); + this.value = queryHintAnnotation.getValue(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setName_(this.queryHintAnnotation.getName()); + this.setValue_(this.queryHintAnnotation.getValue()); + } + + + // ********** name ********** + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.queryHintAnnotation.setName(name); + this.setName_(name); + } + + protected void setName_(String name) { + String old = this.name; + this.name = name; + this.firePropertyChanged(NAME_PROPERTY, old, name); + } + + + // ********** value ********** + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.queryHintAnnotation.setValue(value); + this.setValue_(value); + } + + protected void setValue_(String value) { + String old = this.value; + this.value = value; + this.firePropertyChanged(VALUE_PROPERTY, old, value); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.queryHintAnnotation.getTextRange(astRoot); + } + + + // ********** miscelleneous ********** + + public QueryHintAnnotation getQueryHintAnnotation() { + return this.queryHintAnnotation; + } + + @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/jpa1/context/java/GenericJavaReferenceTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaReferenceTable.java new file mode 100644 index 0000000000..5f8c567183 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaReferenceTable.java @@ -0,0 +1,317 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.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.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyReferenceTable; +import org.eclipse.jpt.jpa.core.context.java.JavaJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaReferenceTable; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.MappingTools; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaTable; +import org.eclipse.jpt.jpa.core.internal.resource.java.NullJoinColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.JoinColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.ReferenceTableAnnotation; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Java join table or collection table + */ +public abstract class GenericJavaReferenceTable<A extends ReferenceTableAnnotation> + extends AbstractJavaTable<A> + implements JavaReferenceTable +{ + protected final Vector<JavaJoinColumn> specifiedJoinColumns = new Vector<JavaJoinColumn>(); + protected final SpecifiedJoinColumnContainerAdapter specifiedJoinColumnContainerAdapter = new SpecifiedJoinColumnContainerAdapter(); + protected final JavaJoinColumn.Owner joinColumnOwner; + + protected JavaJoinColumn defaultJoinColumn; + + + protected GenericJavaReferenceTable(JavaJpaContextNode parent, Owner owner) { + super(parent, owner); + 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(); + } + + public void convertDefaultToSpecifiedJoinColumn() { + MappingTools.convertReferenceTableDefaultToSpecifiedJoinColumn(this); + } + + + // ********** 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.getTableAnnotation().addJoinColumn(index); + return this.addSpecifiedJoinColumn_(index, annotation); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedJoinColumn(this.specifiedJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedJoinColumn(int index) { + this.getTableAnnotation().removeJoinColumn(index); + this.removeTableAnnotationIfUnset(); + 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.getTableAnnotation().moveJoinColumn(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.getTableAnnotation().joinColumns()); + } + + 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)); + } + + /** + * specified join column container adapter + */ + protected class SpecifiedJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<JavaJoinColumn, JoinColumnAnnotation> + { + public Iterable<JavaJoinColumn> getContextElements() { + return GenericJavaReferenceTable.this.getSpecifiedJoinColumns(); + } + public Iterable<JoinColumnAnnotation> getResourceElements() { + return GenericJavaReferenceTable.this.getJoinColumnAnnotations(); + } + public JoinColumnAnnotation getResourceElement(JavaJoinColumn contextElement) { + return contextElement.getColumnAnnotation(); + } + public void moveContextElement(int index, JavaJoinColumn element) { + GenericJavaReferenceTable.this.moveSpecifiedJoinColumn_(index, element); + } + public void addContextElement(int index, JoinColumnAnnotation resourceElement) { + GenericJavaReferenceTable.this.addSpecifiedJoinColumn_(index, resourceElement); + } + public void removeContextElement(JavaJoinColumn element) { + GenericJavaReferenceTable.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(new NullJoinColumnAnnotation(this.getTableAnnotation()))); + } else { + this.defaultJoinColumn.update(); + } + } else { + this.setDefaultJoinColumn(null); + } + } + + protected boolean buildsDefaultJoinColumn() { + return ! this.hasSpecifiedJoinColumns(); + } + + + // ********** misc ********** + + protected void initializeFrom(ReadOnlyReferenceTable oldTable) { + super.initializeFrom(oldTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(oldTable.specifiedJoinColumns())) { + this.addSpecifiedJoinColumn().initializeFrom(joinColumn); + } + } + + protected void initializeFromVirtual(ReadOnlyReferenceTable virtualTable) { + super.initializeFromVirtual(virtualTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(virtualTable.joinColumns())) { + this.addSpecifiedJoinColumn().initializeFromVirtual(joinColumn); + } + } + + protected JavaJoinColumn buildJoinColumn(JoinColumnAnnotation joinColumnAnnotation) { + return this.buildJoinColumn(this.joinColumnOwner, joinColumnAnnotation); + } + + protected JavaJoinColumn buildJoinColumn(JavaJoinColumn.Owner jcOwner, JoinColumnAnnotation joinColumnAnnotation) { + return this.getJpaFactory().buildJavaJoinColumn(this, jcOwner, joinColumnAnnotation); + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** Java completion proposals ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaJoinColumn column : CollectionTools.iterable(this.joinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + boolean continueValidating = this.buildTableValidator(astRoot).validate(messages, reporter); + + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + this.validateJoinColumns(messages, reporter, astRoot); + } + } + + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + this.validateJoinColumns(this.joinColumns(), messages, reporter, astRoot); + } + + protected void validateJoinColumns(Iterator<JavaJoinColumn> joinColumns, List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + while (joinColumns.hasNext()) { + joinColumns.next().validate(messages, reporter, astRoot); + } + } +} + diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java new file mode 100644 index 0000000000..d65b862cc4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSecondaryTable.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.java; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.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.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.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +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.JavaBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaEntity; +import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaSecondaryTable; +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.context.java.AbstractJavaTable; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.SecondaryTablePrimaryKeyJoinColumnValidator; +import org.eclipse.jpt.jpa.core.internal.resource.java.NullPrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.PrimaryKeyJoinColumnAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.SecondaryTableAnnotation; +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 secondary table + */ +public class GenericJavaSecondaryTable + extends AbstractJavaTable<SecondaryTableAnnotation> + implements JavaSecondaryTable +{ + /** @see AbstractJavaTable#AbstractJavaTable(org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode, org.eclipse.jpt.jpa.core.context.Table.Owner, org.eclipse.jpt.jpa.core.resource.java.BaseTableAnnotation) */ + protected /* final */ SecondaryTableAnnotation tableAnnotation; + + protected final Vector<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns = new Vector<JavaPrimaryKeyJoinColumn>(); + protected final SpecifiedPrimaryKeyJoinColumnContainerAdapter specifiedPrimaryKeyJoinColumnContainerAdapter = new SpecifiedPrimaryKeyJoinColumnContainerAdapter(); + protected final JavaBaseJoinColumn.Owner primaryKeyJoinColumnOwner; + + protected JavaPrimaryKeyJoinColumn defaultPrimaryKeyJoinColumn; + + + public GenericJavaSecondaryTable(JavaEntity parent, Owner owner, SecondaryTableAnnotation tableAnnotation) { + super(parent, owner, tableAnnotation); + this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner(); + this.initializeSpecifiedPrimaryKeyJoinColumns(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedPrimaryKeyJoinColumns(); + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedPrimaryKeyJoinColumns()); + this.updateDefaultPrimaryKeyJoinColumn(); + } + + + // ********** table annotation ********** + + @Override + public SecondaryTableAnnotation getTableAnnotation() { + return this.tableAnnotation; + } + + /** + * @see AbstractJavaTable + */ + @Override + protected void setTableAnnotation(SecondaryTableAnnotation tableAnnotation) { + this.tableAnnotation = tableAnnotation; + } + + @Override + protected void removeTableAnnotation() { + // even though its name is required, we don't remove a secondary table' + // annotation when it is empty since it is part of a list and it's not + // obvious whether this would be very user-helpful... + } + + protected String getAnnotationName() { + return SecondaryTableAnnotation.ANNOTATION_NAME; + } + + + // ********** 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.getDefaultPrimaryKeyJoinColumnsSize(); + } + + + // ********** specified primary key join columns ********** + + public ListIterator<JavaPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns() { + return this.getSpecifiedPrimaryKeyJoinColumns().iterator(); + } + + public 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.tableAnnotation.addPkJoinColumn(index); + return this.addSpecifiedPrimaryKeyJoinColumn_(index, annotation); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(PrimaryKeyJoinColumn joinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(int index) { + this.tableAnnotation.removePkJoinColumn(index); + this.removeTableAnnotationIfUnset(); + 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.tableAnnotation.movePkJoinColumn(targetIndex, sourceIndex); + this.moveItemInList(targetIndex, sourceIndex, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + protected void initializeSpecifiedPrimaryKeyJoinColumns() { + for (PrimaryKeyJoinColumnAnnotation annotation : this.getPrimaryKeyJoinColumnAnnotations()) { + this.specifiedPrimaryKeyJoinColumns.add(this.buildPrimaryKeyJoinColumn(annotation)); + } + } + + protected void syncSpecifiedPrimaryKeyJoinColumns() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedPrimaryKeyJoinColumnContainerAdapter); + } + + protected Iterable<PrimaryKeyJoinColumnAnnotation> getPrimaryKeyJoinColumnAnnotations() { + return CollectionTools.iterable(this.tableAnnotation.pkJoinColumns()); + } + + protected void moveSpecifiedPrimaryKeyJoinColumn_(int index, JavaPrimaryKeyJoinColumn joinColumn) { + this.moveItemInList(index, joinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + protected JavaPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn_(int index, PrimaryKeyJoinColumnAnnotation pkJoinColumnAnnotation) { + JavaPrimaryKeyJoinColumn joinColumn = this.buildPrimaryKeyJoinColumn(pkJoinColumnAnnotation); + this.addItemToList(index, joinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + return joinColumn; + } + + protected void removeSpecifiedPrimaryKeyJoinColumn_(JavaPrimaryKeyJoinColumn joinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn_(this.specifiedPrimaryKeyJoinColumns.indexOf(joinColumn)); + } + + /** + * specified primary key join column container adapter + */ + protected class SpecifiedPrimaryKeyJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<JavaPrimaryKeyJoinColumn, PrimaryKeyJoinColumnAnnotation> + { + public Iterable<JavaPrimaryKeyJoinColumn> getContextElements() { + return GenericJavaSecondaryTable.this.getSpecifiedPrimaryKeyJoinColumns(); + } + public Iterable<PrimaryKeyJoinColumnAnnotation> getResourceElements() { + return GenericJavaSecondaryTable.this.getPrimaryKeyJoinColumnAnnotations(); + } + public PrimaryKeyJoinColumnAnnotation getResourceElement(JavaPrimaryKeyJoinColumn contextElement) { + return contextElement.getColumnAnnotation(); + } + public void moveContextElement(int index, JavaPrimaryKeyJoinColumn element) { + GenericJavaSecondaryTable.this.moveSpecifiedPrimaryKeyJoinColumn_(index, element); + } + public void addContextElement(int index, PrimaryKeyJoinColumnAnnotation resourceElement) { + GenericJavaSecondaryTable.this.addSpecifiedPrimaryKeyJoinColumn_(index, resourceElement); + } + public void removeContextElement(JavaPrimaryKeyJoinColumn element) { + GenericJavaSecondaryTable.this.removeSpecifiedPrimaryKeyJoinColumn_(element); + } + } + + protected JavaBaseJoinColumn.Owner buildPrimaryKeyJoinColumnOwner() { + return new PrimaryKeyJoinColumnOwner(); + } + + + // ********** default primary key join column ********** + + public JavaPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() { + return this.defaultPrimaryKeyJoinColumn; + } + + protected void setDefaultPrimaryKeyJoinColumn(JavaPrimaryKeyJoinColumn joinColumn) { + JavaPrimaryKeyJoinColumn old = this.defaultPrimaryKeyJoinColumn; + this.defaultPrimaryKeyJoinColumn = joinColumn; + this.firePropertyChanged(DEFAULT_PRIMARY_KEY_JOIN_COLUMN, old, joinColumn); + } + + protected ListIterable<JavaPrimaryKeyJoinColumn> getDefaultPrimaryKeyJoinColumns() { + return (this.defaultPrimaryKeyJoinColumn != null) ? + new SingleElementListIterable<JavaPrimaryKeyJoinColumn>(this.defaultPrimaryKeyJoinColumn) : + EmptyListIterable.<JavaPrimaryKeyJoinColumn>instance(); + } + + protected int getDefaultPrimaryKeyJoinColumnsSize() { + return (this.defaultPrimaryKeyJoinColumn == null) ? 0 : 1; + } + + protected void updateDefaultPrimaryKeyJoinColumn() { + if (this.buildsDefaultPrimaryKeyJoinColumn()) { + if (this.defaultPrimaryKeyJoinColumn == null) { + this.setDefaultPrimaryKeyJoinColumn(this.buildPrimaryKeyJoinColumn(new NullPrimaryKeyJoinColumnAnnotation(this.tableAnnotation))); + } else { + this.defaultPrimaryKeyJoinColumn.update(); + } + } else { + this.setDefaultPrimaryKeyJoinColumn(null); + } + } + + protected boolean buildsDefaultPrimaryKeyJoinColumn() { + return ! this.hasSpecifiedPrimaryKeyJoinColumns(); + } + + + // ********** misc ********** + + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + protected JavaEntity getEntity() { + return this.getParent(); + } + + public boolean isVirtual() { + return false; + } + + protected JavaPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(PrimaryKeyJoinColumnAnnotation pkJoinColumnAnnotation) { + return this.getJpaFactory().buildJavaPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner, pkJoinColumnAnnotation); + } + + + // ********** defaults ********** + + /** + * a secondary table doesn't have a default name + */ + @Override + protected String buildDefaultName() { + return null; + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** code completion ********** + + @Override + public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + for (JavaPrimaryKeyJoinColumn column : CollectionTools.iterable(this.primaryKeyJoinColumns())) { + result = column.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { + boolean continueValidating = this.buildTableValidator(astRoot).validate(messages, reporter); + + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + for (Iterator<JavaPrimaryKeyJoinColumn> stream = this.primaryKeyJoinColumns(); stream.hasNext(); ) { + stream.next().validate(messages, reporter, astRoot); + } + } + } + + public boolean validatesAgainstDatabase() { + return this.connectionProfileIsActive(); + } + + + // ********** primary key join column owner adapter ********** + + protected class PrimaryKeyJoinColumnOwner + implements JavaBaseJoinColumn.Owner + { + protected JavaEntity getEntity() { + return GenericJavaSecondaryTable.this.getEntity(); + } + + public TypeMapping getTypeMapping() { + return this.getEntity(); + } + + public String getDefaultTableName() { + return GenericJavaSecondaryTable.this.getName(); + } + + public Table resolveDbTable(String tableName) { + return GenericJavaSecondaryTable.this.getDbTable(); + } + + public Table getReferencedColumnDbTable() { + return this.getTypeMapping().getPrimaryDbTable(); + } + + public int joinColumnsSize() { + return GenericJavaSecondaryTable.this.primaryKeyJoinColumnsSize(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericJavaSecondaryTable.this.defaultPrimaryKeyJoinColumn == joinColumn; + } + + public String getDefaultColumnName() { + if (this.joinColumnsSize() != 1) { + return null; + } + return this.getEntity().getPrimaryKeyColumnName(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return GenericJavaSecondaryTable.this.getValidationTextRange(astRoot); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return new SecondaryTablePrimaryKeyJoinColumnValidator(GenericJavaSecondaryTable.this, (BaseJoinColumn) column, this, (BaseJoinColumnTextRangeResolver) textRangeResolver); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java new file mode 100644 index 0000000000..88c717be27 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaSequenceGenerator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaSequenceGenerator; +import org.eclipse.jpt.jpa.core.resource.java.SequenceGeneratorAnnotation; + +/** + * Java sequence generator + */ +public class GenericJavaSequenceGenerator + extends AbstractJavaSequenceGenerator<SequenceGeneratorAnnotation> +{ + public GenericJavaSequenceGenerator(JavaJpaContextNode parent, SequenceGeneratorAnnotation generatorAnnotation) { + super(parent, generatorAnnotation); + } + + + // ********** database stuff ********** + + /** + * The JPA 1.0 spec does not allow a sequence to specify a catalog. + */ + @Override + protected String getCatalog() { + return this.getContextDefaultCatalog(); + } + + /** + * The JPA 1.0 spec does not allow a sequence to specify a schema. + */ + @Override + protected String getSchema() { + return this.getContextDefaultSchema(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTable.java new file mode 100644 index 0000000000..5b2a3ab0a7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTable.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaEntity; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaTable; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.jpa.core.resource.java.TableAnnotation; + +/** + * Java table + */ +public class GenericJavaTable + extends AbstractJavaTable<TableAnnotation> +{ + public GenericJavaTable(JavaEntity parent, Owner owner) { + super(parent, owner); + } + + + // ********** table annotation ********** + + @Override + public TableAnnotation getTableAnnotation() { + // TODO get the NullTableAnnotation from the resource model or build it here in the context model?? + return (TableAnnotation) this.getResourcePersistentType().getNonNullAnnotation(this.getAnnotationName()); + } + + @Override + protected void removeTableAnnotation() { + this.getResourcePersistentType().removeAnnotation(this.getAnnotationName()); + } + + protected String getAnnotationName() { + return TableAnnotation.ANNOTATION_NAME; + } + + protected JavaResourcePersistentType getResourcePersistentType() { + return this.getEntity().getPersistentType().getResourcePersistentType(); + } + + + // ********** defaults ********** + + @Override + protected String buildDefaultName() { + return this.getEntity().getDefaultTableName(); + } + + /** + * Just to remember:<ol> + * <li>{@link org.eclipse.jpt.jpa.core.context.Entity#getDefaultSchema()}<br> + * check inheritance; get default schema from root + * <li>{@link org.eclipse.jpt.jpa.core.context.orm.EntityMappings#getSchema()}<br> + * check for specified schema + * <li>{@link org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit#getDefaultSchema()}<br> + * {@link org.eclipse.jpt.jpa.core.context.orm.OrmPersistenceUnitDefaults#getSchema()} + * <li>{@link org.eclipse.jpt.jpa.core.JpaProject#getDefaultSchema()}<br> + * check for user override project setting + * <li>{@link org.eclipse.jpt.jpa.db.Catalog#getDefaultSchema()}<br> + * or {@link org.eclipse.jpt.jpa.db.Database#getDefaultSchema()} + * </ol> + */ + @Override + protected String buildDefaultSchema() { + return this.getEntity().getDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getEntity().getDefaultCatalog(); + } + + + // ********** validation ********** + + public boolean validatesAgainstDatabase() { + return this.connectionProfileIsActive(); + } + + + // ********** misc ********** + + /** + * covariant override + */ + @Override + public JavaEntity getParent() { + return (JavaEntity) super.getParent(); + } + + protected JavaEntity getEntity() { + return this.getParent(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTableGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTableGenerator.java new file mode 100644 index 0000000000..f553c9b717 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTableGenerator.java @@ -0,0 +1,567 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.Iterator; +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.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.LiveCloneIterable; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator; +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.JavaTableGenerator; +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.java.AbstractJavaGenerator; +import org.eclipse.jpt.jpa.core.resource.java.TableGeneratorAnnotation; +import org.eclipse.jpt.jpa.core.resource.java.UniqueConstraintAnnotation; +import org.eclipse.jpt.jpa.db.Database; +import org.eclipse.jpt.jpa.db.Schema; +import org.eclipse.jpt.jpa.db.SchemaContainer; +import org.eclipse.jpt.jpa.db.Table; + +/** + * Java table generator + */ +public class GenericJavaTableGenerator + extends AbstractJavaGenerator<TableGeneratorAnnotation> + implements JavaTableGenerator, UniqueConstraint.Owner +{ + protected String specifiedTable; + protected String defaultTable; + + protected String specifiedSchema; + protected String defaultSchema; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedPkColumnName; + protected String defaultPkColumnName; + + protected String specifiedValueColumnName; + protected String defaultValueColumnName; + + protected String specifiedPkColumnValue; + protected String defaultPkColumnValue; + + protected final Vector<JavaUniqueConstraint> uniqueConstraints = new Vector<JavaUniqueConstraint>(); + protected final UniqueConstraintContainerAdapter uniqueConstraintContainerAdapter = new UniqueConstraintContainerAdapter(); + + + // ********** constructor ********** + + public GenericJavaTableGenerator(JavaJpaContextNode parent, TableGeneratorAnnotation generatorAnnotation) { + super(parent, generatorAnnotation); + this.specifiedTable = generatorAnnotation.getTable(); + this.specifiedSchema = generatorAnnotation.getSchema(); + this.specifiedCatalog = generatorAnnotation.getCatalog(); + this.specifiedPkColumnName = generatorAnnotation.getPkColumnName(); + this.specifiedValueColumnName = generatorAnnotation.getValueColumnName(); + this.specifiedPkColumnValue = generatorAnnotation.getPkColumnValue(); + this.initializeUniqueConstraints(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedTable_(this.generatorAnnotation.getTable()); + this.setSpecifiedSchema_(this.generatorAnnotation.getSchema()); + this.setSpecifiedCatalog_(this.generatorAnnotation.getCatalog()); + this.setSpecifiedPkColumnName_(this.generatorAnnotation.getPkColumnName()); + this.setSpecifiedValueColumnName_(this.generatorAnnotation.getValueColumnName()); + this.setSpecifiedPkColumnValue_(this.generatorAnnotation.getPkColumnValue()); + this.syncUniqueConstraints(); + } + + @Override + public void update() { + super.update(); + this.setDefaultTable(this.buildDefaultTable()); + this.setDefaultSchema(this.buildDefaultSchema()); + this.setDefaultCatalog(this.buildDefaultCatalog()); + this.setDefaultPkColumnName(this.buildDefaultPkColumnName()); + this.setDefaultValueColumnName(this.buildDefaultValueColumnName()); + this.setDefaultPkColumnValue(this.buildDefaultPkColumnValue()); + this.updateNodes(this.getUniqueConstraints()); + } + + + // ********** initial value ********** + + @Override + protected int buildDefaultInitialValue() { + return DEFAULT_INITIAL_VALUE; + } + + + // ********** table ********** + + public String getTable() { + return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable; + } + + public String getSpecifiedTable() { + return this.specifiedTable; + } + + public void setSpecifiedTable(String table) { + this.generatorAnnotation.setTable(table); + this.setSpecifiedTable_(table); + } + + protected void setSpecifiedTable_(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + public String getDefaultTable() { + return this.defaultTable; + } + + protected void setDefaultTable(String table) { + String old = this.defaultTable; + this.defaultTable = table; + this.firePropertyChanged(DEFAULT_TABLE_PROPERTY, old, table); + } + + protected String buildDefaultTable() { + return null; // TODO the default table is determined by the runtime provider... + } + + public Table getDbTable() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getTable()); + } + + + // ********** schema ********** + + @Override + public String getSchema() { + return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema; + } + + public String getSpecifiedSchema() { + return this.specifiedSchema; + } + + public void setSpecifiedSchema(String schema) { + this.generatorAnnotation.setSchema(schema); + this.setSpecifiedSchema_(schema); + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + public String getDefaultSchema() { + return this.defaultSchema; + } + + protected void setDefaultSchema(String schema) { + String old = this.defaultSchema; + this.defaultSchema = schema; + this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema); + } + + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + + // ********** catalog ********** + + @Override + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + this.generatorAnnotation.setCatalog(catalog); + this.setSpecifiedCatalog_(catalog); + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + public String getDefaultCatalog() { + return this.defaultCatalog; + } + + protected void setDefaultCatalog(String catalog) { + String old = this.defaultCatalog; + this.defaultCatalog = catalog; + this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog); + } + + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** primary key column name ********** + + public String getPkColumnName() { + return (this.specifiedPkColumnName != null) ? this.specifiedPkColumnName : this.defaultPkColumnName; + } + + public String getSpecifiedPkColumnName() { + return this.specifiedPkColumnName; + } + + public void setSpecifiedPkColumnName(String name) { + this.generatorAnnotation.setPkColumnName(name); + this.setSpecifiedPkColumnName_(name); + } + + protected void setSpecifiedPkColumnName_(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultPkColumnName() { + return this.defaultPkColumnName; + } + + protected void setDefaultPkColumnName(String name) { + String old = this.defaultPkColumnName; + this.defaultPkColumnName = name; + this.firePropertyChanged(DEFAULT_PK_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultPkColumnName() { + return null; // TODO the default pk column name is determined by the runtime provider... + } + + + // ********** value column name ********** + + public String getValueColumnName() { + return (this.specifiedValueColumnName != null) ? this.specifiedValueColumnName : this.defaultValueColumnName; + } + + public String getSpecifiedValueColumnName() { + return this.specifiedValueColumnName; + } + + public void setSpecifiedValueColumnName(String name) { + this.generatorAnnotation.setValueColumnName(name); + this.setSpecifiedValueColumnName_(name); + } + + protected void setSpecifiedValueColumnName_(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultValueColumnName() { + return this.defaultValueColumnName; + } + + protected void setDefaultValueColumnName(String name) { + String old = this.defaultValueColumnName; + this.defaultValueColumnName = name; + this.firePropertyChanged(DEFAULT_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultValueColumnName() { + return null; // TODO the default value column name is determined by the runtime provider... + } + + + // ********** primary key column value ********** + + public String getPkColumnValue() { + return (this.specifiedPkColumnValue != null) ? this.specifiedPkColumnValue : this.defaultPkColumnValue; + } + + public String getSpecifiedPkColumnValue() { + return this.specifiedPkColumnValue; + } + + public void setSpecifiedPkColumnValue(String value) { + this.generatorAnnotation.setPkColumnValue(value); + this.setSpecifiedPkColumnValue_(value); + } + + protected void setSpecifiedPkColumnValue_(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + public String getDefaultPkColumnValue() { + return this.defaultPkColumnValue; + } + + protected void setDefaultPkColumnValue(String value) { + String old = this.defaultPkColumnValue; + this.defaultPkColumnValue = value; + this.firePropertyChanged(DEFAULT_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + protected String buildDefaultPkColumnValue() { + return null; // TODO the default pk column value is determined by the runtime provider... + } + + + // ********** unique constraints ********** + + public Iterable<JavaUniqueConstraint> getUniqueConstraints() { + return new LiveCloneIterable<JavaUniqueConstraint>(this.uniqueConstraints); + } + + public int getUniqueConstraintsSize() { + return this.uniqueConstraints.size(); + } + + public JavaUniqueConstraint addUniqueConstraint() { + return this.addUniqueConstraint(this.uniqueConstraints.size()); + } + + public JavaUniqueConstraint addUniqueConstraint(int index) { + UniqueConstraintAnnotation constraintAnnotation = this.generatorAnnotation.addUniqueConstraint(index); + return this.addUniqueConstraint_(index, constraintAnnotation); + } + + public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) { + this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + public void removeUniqueConstraint(int index) { + this.generatorAnnotation.removeUniqueConstraint(index); + this.removeUniqueConstraint_(index); + } + + protected void removeUniqueConstraint_(int index) { + this.removeItemFromList(index, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + public void moveUniqueConstraint(int targetIndex, int sourceIndex) { + this.generatorAnnotation.moveUniqueConstraint(targetIndex, sourceIndex); + this.moveItemInList(targetIndex, sourceIndex, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + protected void initializeUniqueConstraints() { + for (Iterator<UniqueConstraintAnnotation> stream = this.generatorAnnotation.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.generatorAnnotation.uniqueConstraints()); + } + + protected void moveUniqueConstraint_(int index, JavaUniqueConstraint uniqueConstraint) { + this.moveItemInList(index, uniqueConstraint, 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 uniqueConstraint) { + this.removeUniqueConstraint_(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + /** + * unique constraint container adapter + */ + protected class UniqueConstraintContainerAdapter + implements ContextContainerTools.Adapter<JavaUniqueConstraint, UniqueConstraintAnnotation> + { + public Iterable<JavaUniqueConstraint> getContextElements() { + return GenericJavaTableGenerator.this.getUniqueConstraints(); + } + public Iterable<UniqueConstraintAnnotation> getResourceElements() { + return GenericJavaTableGenerator.this.getUniqueConstraintAnnotations(); + } + public UniqueConstraintAnnotation getResourceElement(JavaUniqueConstraint contextElement) { + return contextElement.getUniqueConstraintAnnotation(); + } + public void moveContextElement(int index, JavaUniqueConstraint element) { + GenericJavaTableGenerator.this.moveUniqueConstraint_(index, element); + } + public void addContextElement(int index, UniqueConstraintAnnotation resourceElement) { + GenericJavaTableGenerator.this.addUniqueConstraint_(index, resourceElement); + } + public void removeContextElement(JavaUniqueConstraint element) { + GenericJavaTableGenerator.this.removeUniqueConstraint_(element); + } + } + + + // ********** 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 : this.getUniqueConstraints()) { + result = constraint.javaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + } + return null; + } + + /** + * called if the database is connected: + * table, schema, catalog, pkColumnName, valueColumnName + */ + @Override + public Iterator<String> connectedJavaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) { + Iterator<String> result = super.connectedJavaCompletionProposals(pos, filter, astRoot); + if (result != null) { + return result; + } + if (this.tableTouches(pos, astRoot)) { + return this.getJavaCandidateTables(filter).iterator(); + } + if (this.schemaTouches(pos, astRoot)) { + return this.getJavaCandidateSchemata(filter).iterator(); + } + if (this.catalogTouches(pos, astRoot)) { + return this.getJavaCandidateCatalogs(filter).iterator(); + } + if (this.pkColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateColumnNames(filter).iterator(); + } + if (this.valueColumnNameTouches(pos, astRoot)) { + return this.getJavaCandidateColumnNames(filter).iterator(); + } + return null; + } + + // ********** code assist: table + + protected boolean tableTouches(int pos, CompilationUnit astRoot) { + return this.generatorAnnotation.tableTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateTables(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateTables(filter)); + } + + protected Iterable<String> getCandidateTables(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateTables(), filter); + } + + protected Iterable<String> getCandidateTables() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema != null) ? dbSchema.getSortedTableIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: schema + + protected boolean schemaTouches(int pos, CompilationUnit astRoot) { + return this.generatorAnnotation.schemaTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateSchemata(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateSchemata(filter)); + } + + protected Iterable<String> getCandidateSchemata(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateSchemata(), filter); + } + + protected Iterable<String> getCandidateSchemata() { + SchemaContainer schemaContainer = this.getDbSchemaContainer(); + return (schemaContainer != null) ? schemaContainer.getSortedSchemaIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: catalog + + protected boolean catalogTouches(int pos, CompilationUnit astRoot) { + return this.generatorAnnotation.catalogTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateCatalogs(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateCatalogs(filter)); + } + + protected Iterable<String> getCandidateCatalogs(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateCatalogs(), filter); + } + + protected Iterable<String> getCandidateCatalogs() { + Database db = this.getDatabase(); + return (db != null) ? db.getSortedCatalogIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: pkColumnName + + protected boolean pkColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.generatorAnnotation.pkColumnNameTouches(pos, astRoot); + } + + protected Iterable<String> getJavaCandidateColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.getCandidateColumnNames(filter)); + } + + protected Iterable<String> getCandidateColumnNames(Filter<String> filter) { + return new FilteringIterable<String>(this.getCandidateColumnNames(), filter); + } + + protected Iterable<String> getCandidateColumnNames() { + Table table = this.getDbTable(); + return (table != null) ? table.getSortedColumnIdentifiers() : EmptyIterable.<String> instance(); + } + + // ********** code assist: valueColumnName + + protected boolean valueColumnNameTouches(int pos, CompilationUnit astRoot) { + return this.generatorAnnotation.valueColumnNameTouches(pos, astRoot); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java new file mode 100644 index 0000000000..a48e67aeb5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTemporalConverter.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.TemporalConverter; +import org.eclipse.jpt.jpa.core.context.TemporalType; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaTemporalConverter; +import org.eclipse.jpt.jpa.core.resource.java.TemporalAnnotation; + +public class GenericJavaTemporalConverter + extends AbstractJavaConverter + implements JavaTemporalConverter +{ + protected final TemporalAnnotation temporalAnnotation; + + protected TemporalType temporalType; + + + public GenericJavaTemporalConverter(JavaAttributeMapping parent, TemporalAnnotation temporalAnnotation) { + super(parent); + this.temporalAnnotation = temporalAnnotation; + this.temporalType = this.buildTemporalType(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setTemporalType_(this.buildTemporalType()); + } + + + // ********** temporal type ********** + + public TemporalType getTemporalType() { + return this.temporalType; + } + + public void setTemporalType(TemporalType temporalType) { + if (this.valuesAreDifferent(this.temporalType, temporalType)) { + this.temporalAnnotation.setValue(TemporalType.toJavaResourceModel(temporalType)); + this.removeTemporalAnnotationIfUnset(); + this.setTemporalType_(temporalType); + } + } + + protected void setTemporalType_(TemporalType temporalType) { + TemporalType old = this.temporalType; + this.temporalType = temporalType; + this.firePropertyChanged(TEMPORAL_TYPE_PROPERTY, old, temporalType); + } + + protected TemporalType buildTemporalType() { + return TemporalType.fromJavaResourceModel(this.temporalAnnotation.getValue()); + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return TemporalConverter.class; + } + + @Override + protected String getAnnotationName() { + return TemporalAnnotation.ANNOTATION_NAME; + } + + protected void removeTemporalAnnotationIfUnset() { + if (this.temporalAnnotation.isUnset()) { + this.temporalAnnotation.removeAnnotation(); + } + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.temporalAnnotation.getTextRange(astRoot); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTransientMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTransientMapping.java new file mode 100644 index 0000000000..37e46c1c56 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaTransientMapping.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.java.JavaTransientMapping; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaAttributeMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.jpa.core.resource.java.TransientAnnotation; + +/** + * Java transient mapping + */ +public class GenericJavaTransientMapping + extends AbstractJavaAttributeMapping<TransientAnnotation> + implements JavaTransientMapping +{ + public GenericJavaTransientMapping(JavaPersistentAttribute parent) { + super(parent); + } + + public String getKey() { + return MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY; + } + + @Override + protected String getAnnotationName() { + return TransientAnnotation.ANNOTATION_NAME; + } + + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java new file mode 100644 index 0000000000..43eef86ff7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaUniqueConstraint.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * 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.jpa1.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.CollectionTools; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.jpa.core.context.ReadOnlyUniqueConstraint; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaUniqueConstraint; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaReadOnlyUniqueConstraint; +import org.eclipse.jpt.jpa.core.resource.java.UniqueConstraintAnnotation; + +public class GenericJavaUniqueConstraint + extends AbstractJavaReadOnlyUniqueConstraint + implements JavaUniqueConstraint +{ + protected Owner owner; + protected final UniqueConstraintAnnotation uniqueConstraintAnnotation; + + + public GenericJavaUniqueConstraint(JavaJpaContextNode parent, Owner owner, UniqueConstraintAnnotation uniqueConstraintAnnotation) { + super(parent); + this.owner = owner; + this.uniqueConstraintAnnotation = uniqueConstraintAnnotation; + this.initializeColumnNames(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncColumnNames(); + } + + + // ********** column names ********** + + public void addColumnName(String columnName) { + this.addColumnName(this.columnNames.size(), columnName); + } + + public void addColumnName(int index, String columnName) { + this.uniqueConstraintAnnotation.addColumnName(index, columnName); + this.addItemToList(index, columnName, this.columnNames, COLUMN_NAMES_LIST); + } + + public void removeColumnName(String columnName) { + this.removeColumnName(this.columnNames.indexOf(columnName)); + } + + public void removeColumnName(int index) { + this.uniqueConstraintAnnotation.removeColumnName(index); + this.removeItemFromList(index, this.columnNames, COLUMN_NAMES_LIST); + } + + public void moveColumnName(int targetIndex, int sourceIndex) { + this.uniqueConstraintAnnotation.moveColumnName(targetIndex, sourceIndex); + this.moveItemInList(targetIndex, sourceIndex, this.columnNames, COLUMN_NAMES_LIST); + } + + protected void initializeColumnNames() { + for (Iterator<String> stream = this.uniqueConstraintAnnotation.columnNames(); stream.hasNext(); ) { + this.columnNames.add(stream.next()); + } + } + + @Override + protected Iterable<String> getResourceColumnNames() { + return CollectionTools.iterable(this.uniqueConstraintAnnotation.columnNames()); + } + + // ********** 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.columnNamesTouches(pos, astRoot)) { + return this.javaCandidateColumnNames(filter); + } + return null; + } + + protected boolean columnNamesTouches(int pos, CompilationUnit astRoot) { + return this.uniqueConstraintAnnotation.columnNamesTouches(pos, astRoot); + } + + protected Iterator<String> javaCandidateColumnNames(Filter<String> filter) { + return StringTools.convertToJavaStringLiterals(this.candidateColumnNames(filter)); + } + + protected Iterator<String> candidateColumnNames(Filter<String> filter) { + return new FilteringIterator<String>(this.candidateColumnNames(), filter); + } + + protected Iterator<String> candidateColumnNames() { + return this.owner.candidateUniqueConstraintColumnNames(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return this.uniqueConstraintAnnotation.getTextRange(astRoot); + } + + + // ********** misc ********** + + public UniqueConstraintAnnotation getUniqueConstraintAnnotation() { + return this.uniqueConstraintAnnotation; + } + + public void initializeFrom(ReadOnlyUniqueConstraint oldUniqueConstraint) { + for (String columnName : oldUniqueConstraint.getColumnNames()) { + this.addColumnName(columnName); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVersionMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVersionMapping.java new file mode 100644 index 0000000000..9d66e365f5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVersionMapping.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaVersionMapping; + +public class GenericJavaVersionMapping + extends AbstractJavaVersionMapping +{ + public GenericJavaVersionMapping(JavaPersistentAttribute parent) { + super(parent); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAssociationOverride.java new file mode 100644 index 0000000000..2333e0c4d1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAssociationOverride.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +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.JavaVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverrideRelationship; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaVirtualOverride; + +/** + * Virtual Java association override + */ +public class GenericJavaVirtualAssociationOverride + extends AbstractJavaVirtualOverride<JavaAssociationOverrideContainer> + implements JavaVirtualAssociationOverride +{ + protected final JavaVirtualOverrideRelationship relationship; + + + public GenericJavaVirtualAssociationOverride(JavaAssociationOverrideContainer parent, String name) { + super(parent, name); + this.relationship = this.buildRelationship(); + } + + @Override + public void update() { + super.update(); + this.relationship.update(); + } + + @Override + public JavaAssociationOverride convertToSpecified() { + return (JavaAssociationOverride) super.convertToSpecified(); + } + + public RelationshipMapping getMapping() { + return this.getContainer().getRelationshipMapping(this.name); + } + + + // ********** relationship ********** + + public JavaVirtualOverrideRelationship getRelationship() { + return this.relationship; + } + + /** + * The relationship should be available (since its presence precipitated the + * creation of the virtual override). + */ + protected JavaVirtualOverrideRelationship buildRelationship() { + return this.getJpaFactory().buildJavaVirtualOverrideRelationship(this); + } + + public Relationship resolveOverriddenRelationship() { + return this.getContainer().resolveOverriddenRelationship(this.name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAttributeOverride.java new file mode 100644 index 0000000000..9049ad974d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualAttributeOverride.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.ReadOnlyColumn; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualAttributeOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualColumn; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaVirtualOverride; + +/** + * Virtual Java attribute override + */ +public class GenericJavaVirtualAttributeOverride + extends AbstractJavaVirtualOverride<JavaAttributeOverrideContainer> + implements JavaVirtualAttributeOverride, JavaVirtualColumn.Owner +{ + protected final JavaVirtualColumn column; + + + public GenericJavaVirtualAttributeOverride(JavaAttributeOverrideContainer parent, String name) { + super(parent, name); + this.column = this.buildColumn(); + } + + @Override + public void update() { + super.update(); + this.column.update(); + } + + @Override + public JavaAttributeOverride convertToSpecified() { + return (JavaAttributeOverride) super.convertToSpecified(); + } + + + // ********** column ********** + + public JavaVirtualColumn getColumn() { + return this.column; + } + + /** + * The original column should be available (since the presence of its + * attribute is what precipitated the creation of the virtual override). + */ + protected JavaVirtualColumn buildColumn() { + return this.getJpaFactory().buildJavaVirtualColumn(this, this); + } + + + // ********** column owner implementation ********** + + public TypeMapping getTypeMapping() { + return this.getContainer().getTypeMapping(); + } + + public String getDefaultTableName() { + String overriddenColumnTable = this.getOverriddenColumnTable(); + return (overriddenColumnTable != null) ? overriddenColumnTable : this.getContainer().getDefaultTableName(); + } + + protected String getOverriddenColumnTable() { + ReadOnlyColumn overriddenColumn = this.resolveOverriddenColumn(); + // pretty sure this is the *specified* table... + return (overriddenColumn == null) ? null : overriddenColumn.getSpecifiedTable(); + } + + public String getDefaultColumnName() { + String overriddenColumnName = this.getOverriddenColumnName(); + return (overriddenColumnName != null) ? overriddenColumnName : this.name; + } + + protected String getOverriddenColumnName() { + ReadOnlyColumn overriddenColumn = this.resolveOverriddenColumn(); + return (overriddenColumn == null) ? null : overriddenColumn.getName(); + } + + public Column resolveOverriddenColumn() { + return this.getContainer().resolveOverriddenColumn(this.name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualColumn.java new file mode 100644 index 0000000000..0429f71344 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualColumn.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualColumn; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaVirtualBaseColumn; + +/** + * Java virtual column + */ +public class GenericJavaVirtualColumn + extends AbstractJavaVirtualBaseColumn<JavaVirtualColumn.Owner, Column> + implements JavaVirtualColumn +{ + protected Integer specifiedLength; + protected int defaultLength; + + protected Integer specifiedPrecision; + protected int defaultPrecision; + + protected Integer specifiedScale; + protected int defaultScale; + + + public GenericJavaVirtualColumn(JavaJpaContextNode parent, JavaVirtualColumn.Owner owner) { + super(parent, owner); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + + this.setSpecifiedLength(this.buildSpecifiedLength()); + this.setDefaultLength(this.buildDefaultLength()); + + this.setSpecifiedPrecision(this.buildSpecifiedPrecision()); + this.setDefaultPrecision(this.buildDefaultPrecision()); + + this.setSpecifiedScale(this.buildSpecifiedScale()); + this.setDefaultScale(this.buildDefaultScale()); + } + + + // ********** column ********** + + @Override + public Column getOverriddenColumn() { + return this.owner.resolveOverriddenColumn(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.defaultLength; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + protected void setSpecifiedLength(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + return this.getOverriddenColumn().getSpecifiedLength(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int length) { + int old = this.defaultLength; + this.defaultLength = length; + this.firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, length); + } + + protected int buildDefaultLength() { + return DEFAULT_LENGTH; + } + + + // ********** precision ********** + + public int getPrecision() { + return (this.specifiedPrecision != null) ? this.specifiedPrecision.intValue() : this.defaultPrecision; + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + protected void setSpecifiedPrecision(Integer precision) { + Integer old = this.specifiedPrecision; + this.specifiedPrecision = precision; + this.firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, old, precision); + } + + protected Integer buildSpecifiedPrecision() { + return this.getOverriddenColumn().getSpecifiedPrecision(); + } + + public int getDefaultPrecision() { + return this.defaultPrecision; + } + + protected void setDefaultPrecision(int precision) { + int old = this.defaultPrecision; + this.defaultPrecision = precision; + this.firePropertyChanged(DEFAULT_PRECISION_PROPERTY, old, precision); + } + + protected int buildDefaultPrecision() { + return DEFAULT_PRECISION; + } + + + // ********** scale ********** + + public int getScale() { + return (this.specifiedScale != null) ? this.specifiedScale.intValue() : this.defaultScale; + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + protected void setSpecifiedScale(Integer scale) { + Integer old = this.specifiedScale; + this.specifiedScale = scale; + this.firePropertyChanged(SPECIFIED_SCALE_PROPERTY, old, scale); + } + + protected Integer buildSpecifiedScale() { + return this.getOverriddenColumn().getSpecifiedScale(); + } + + public int getDefaultScale() { + return this.defaultScale; + } + + protected void setDefaultScale(int scale) { + int old = this.defaultScale; + this.defaultScale = scale; + this.firePropertyChanged(DEFAULT_SCALE_PROPERTY, old, scale); + } + + protected int buildDefaultScale() { + return DEFAULT_SCALE; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualJoinColumn.java new file mode 100644 index 0000000000..6848cb9c65 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualJoinColumn.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +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.MappingTools; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaVirtualBaseColumn; + +/** + * Java virtual join column + */ +public class GenericJavaVirtualJoinColumn + extends AbstractJavaVirtualBaseColumn<ReadOnlyJoinColumn.Owner, JoinColumn> + implements JavaVirtualJoinColumn +{ + protected final JoinColumn overriddenColumn; + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericJavaVirtualJoinColumn(JavaJpaContextNode parent, ReadOnlyJoinColumn.Owner owner, JoinColumn overriddenColumn) { + super(parent, owner); + this.overriddenColumn = overriddenColumn; + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + + this.setSpecifiedReferencedColumnName(this.buildSpecifiedReferencedColumnName()); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** column ********** + + @Override + public JoinColumn getOverriddenColumn() { + return this.overriddenColumn; + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + protected void setSpecifiedReferencedColumnName(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return this.getOverriddenColumn().getSpecifiedReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.owner); + } + + + // ********** misc ********** + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.owner); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.java new file mode 100644 index 0000000000..aeb114470b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.java @@ -0,0 +1,335 @@ +/******************************************************************************* + * 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.jpa1.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.iterables.EmptyIterable; +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.JoinColumnRelationship; +import org.eclipse.jpt.jpa.core.context.JoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +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.JavaAssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.java.JavaReadOnlyAssociationOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumn; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumnRelationship; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualOverrideRelationship; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; + +public class GenericJavaVirtualOverrideJoinColumnRelationshipStrategy + extends AbstractJavaJpaContextNode + implements JavaVirtualJoinColumnRelationshipStrategy +{ + protected final Vector<JavaVirtualJoinColumn> specifiedJoinColumns = new Vector<JavaVirtualJoinColumn>(); + protected final SpecifiedJoinColumnContainerAdapter specifiedJoinColumnContainerAdapter; + protected final ReadOnlyJoinColumn.Owner joinColumnOwner; + + protected JavaVirtualJoinColumn defaultJoinColumn; + + + public GenericJavaVirtualOverrideJoinColumnRelationshipStrategy(JavaVirtualJoinColumnRelationship parent) { + super(parent); + this.specifiedJoinColumnContainerAdapter = this.buildSpecifiedJoinColumnContainerAdapter(); + 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> getOverriddenSpecifiedJoinColumns() { + JoinColumnRelationshipStrategy overriddenStrategy = this.getOverriddenStrategy(); + return (overriddenStrategy == null) ? + EmptyIterable.<JoinColumn>instance() : + CollectionTools.iterable(overriddenStrategy.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); + } + + protected SpecifiedJoinColumnContainerAdapter buildSpecifiedJoinColumnContainerAdapter() { + return new SpecifiedJoinColumnContainerAdapter(); + } + + /** + * specified join column container adapter + */ + protected class SpecifiedJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<JavaVirtualJoinColumn, JoinColumn> + { + public Iterable<JavaVirtualJoinColumn> getContextElements() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getSpecifiedJoinColumns(); + } + public Iterable<JoinColumn> getResourceElements() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getOverriddenSpecifiedJoinColumns(); + } + public JoinColumn getResourceElement(JavaVirtualJoinColumn contextElement) { + return contextElement.getOverriddenColumn(); + } + public void moveContextElement(int index, JavaVirtualJoinColumn element) { + GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.moveSpecifiedJoinColumn(index, element); + } + public void addContextElement(int index, JoinColumn resourceElement) { + GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.addSpecifiedJoinColumn(index, resourceElement); + } + public void removeContextElement(JavaVirtualJoinColumn element) { + GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.removeSpecifiedJoinColumn(element); + } + } + + protected ReadOnlyJoinColumn.Owner buildJoinColumnOwner() { + return new JoinColumnOwner(); + } + + + // ********** 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() { + JoinColumn overriddenDefaultJoinColumn = this.getOverriddenDefaultJoinColumn(); + if (overriddenDefaultJoinColumn == null) { + if (this.defaultJoinColumn != null) { + this.setDefaultJoinColumn(null); + } + } else { + if ((this.defaultJoinColumn != null) && (this.defaultJoinColumn.getOverriddenColumn() == overriddenDefaultJoinColumn)) { + this.defaultJoinColumn.update(); + } else { + this.setDefaultJoinColumn(this.buildJoinColumn(overriddenDefaultJoinColumn)); + } + } + } + + protected JoinColumn getOverriddenDefaultJoinColumn() { + JoinColumnRelationshipStrategy overriddenStrategy = this.getOverriddenStrategy(); + return (overriddenStrategy == null) ? null : overriddenStrategy.getDefaultJoinColumn(); + } + + + // ********** misc ********** + + @Override + public JavaVirtualJoinColumnRelationship getParent() { + return (JavaVirtualJoinColumnRelationship) super.getParent(); + } + + public JavaVirtualJoinColumnRelationship getRelationship() { + return this.getParent(); + } + + protected JoinColumnRelationshipStrategy getOverriddenStrategy() { + JoinColumnRelationship relationship = this.getOverriddenJoinColumnRelationship(); + return (relationship == null) ? null : relationship.getJoinColumnStrategy(); + } + + protected JoinColumnRelationship getOverriddenJoinColumnRelationship() { + Relationship relationship = this.resolveOverriddenRelationship(); + return (relationship instanceof JoinColumnRelationship) ? (JoinColumnRelationship) relationship : null; + } + + protected Relationship resolveOverriddenRelationship() { + return this.getRelationship().resolveOverriddenRelationship(); + } + + 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; + } + + protected RelationshipMapping getRelationshipMapping() { + return this.getAssociationOverride().getMapping(); + } + + protected JavaReadOnlyAssociationOverride getAssociationOverride() { + return ((JavaVirtualOverrideRelationship) this.getRelationship()).getAssociationOverride(); + } + + protected JavaAssociationOverrideContainer getAssociationOverrideContainer() { + return this.getAssociationOverride().getContainer(); + } + + public String getTableName() { + return this.isTargetForeignKey() ? + this.getSourceTableName() : + this.getAssociationOverrideContainer().getDefaultTableName(); + } + + protected String getSourceTableName() { + TypeMapping typeMapping = this.getRelationshipSource(); + return (typeMapping == null) ? null : typeMapping.getPrimaryTableName(); + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } + + protected String getAttributeName() { + return this.getAssociationOverride().getName(); + } + + protected JavaVirtualJoinColumn buildJoinColumn(JoinColumn overriddenJoinColumn) { + return this.getJpaFactory().buildJavaVirtualJoinColumn(this, this.joinColumnOwner, overriddenJoinColumn); + } + + + // ********** join column owner ********** + + protected class JoinColumnOwner + implements ReadOnlyJoinColumn.Owner + { + protected JoinColumnOwner() { + super(); + } + + public String getDefaultTableName() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getTableName(); + } + + public String getDefaultColumnName() { + //built in MappingTools.buildJoinColumnDefaultName() + return null; + } + + public String getAttributeName() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getAttributeName(); + } + + public TypeMapping getTypeMapping() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getRelationshipSource(); + } + + public Entity getRelationshipTarget() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.getRelationshipTargetEntity(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return false; + } + + public int joinColumnsSize() { + return GenericJavaVirtualOverrideJoinColumnRelationshipStrategy.this.joinColumnsSize(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideRelationship.java new file mode 100644 index 0000000000..b75f1d81a3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualOverrideRelationship.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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.jpa1.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.OverrideRelationship; +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.JavaVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.java.JavaVirtualRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.GenericJavaVirtualOverrideJoinTableRelationshipStrategy2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaVirtualOverrideRelationship2_0; + +public class GenericJavaVirtualOverrideRelationship + extends AbstractJavaJpaContextNode + implements JavaVirtualOverrideRelationship2_0 +{ + protected JavaVirtualRelationshipStrategy strategy; + + protected final JavaVirtualJoinColumnRelationshipStrategy joinColumnStrategy; + + // JPA 2.0 + protected final JavaVirtualJoinTableRelationshipStrategy joinTableStrategy; + + + public GenericJavaVirtualOverrideRelationship(JavaVirtualAssociationOverride parent) { + super(parent); + this.joinColumnStrategy = this.buildJoinColumnStrategy(); + this.joinTableStrategy = this.buildJoinTableStrategy(); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.setStrategy(this.buildStrategy()); + this.joinColumnStrategy.update(); + this.joinTableStrategy.update(); + } + + + // ********** strategy ********** + + public JavaVirtualRelationshipStrategy getStrategy() { + return this.strategy; + } + + protected void setStrategy(JavaVirtualRelationshipStrategy strategy) { + JavaVirtualRelationshipStrategy old = this.strategy; + this.strategy = strategy; + this.firePropertyChanged(STRATEGY_PROPERTY, old, strategy); + } + + protected JavaVirtualRelationshipStrategy buildStrategy() { + if (this.isJpa2_0Compatible()) { + if (this.joinColumnStrategy.hasSpecifiedJoinColumns()) { + return this.joinColumnStrategy; + } + return this.joinTableStrategy; + } + return this.joinColumnStrategy; + } + + + // ********** join column strategy ********** + + public JavaVirtualJoinColumnRelationshipStrategy getJoinColumnStrategy() { + return this.joinColumnStrategy; + } + + public boolean strategyIsJoinColumn() { + return this.strategy == this.joinColumnStrategy; + } + + public boolean mayHaveDefaultJoinColumn() { + return false; + } + + protected JavaVirtualJoinColumnRelationshipStrategy buildJoinColumnStrategy() { + return new GenericJavaVirtualOverrideJoinColumnRelationshipStrategy(this); + } + + + // ********** join table strategy ********** + + public JavaVirtualJoinTableRelationshipStrategy getJoinTableStrategy() { + return this.joinTableStrategy; + } + + public boolean strategyIsJoinTable() { + return this.strategy == this.joinTableStrategy; + } + + public boolean mayHaveDefaultJoinTable() { + return this.isVirtual(); + } + + protected JavaVirtualJoinTableRelationshipStrategy buildJoinTableStrategy() { + return new GenericJavaVirtualOverrideJoinTableRelationshipStrategy2_0(this); + } + + + // ********** conversions ********** + + public void initializeOn(Relationship newRelationship) { + newRelationship.initializeFromJoinTableRelationship(this); + newRelationship.initializeFromJoinColumnRelationship(this); + } + + public void initializeOnSpecified(OverrideRelationship specifiedRelationship) { + specifiedRelationship.initializeFromVirtualJoinColumnRelationship(this); + specifiedRelationship.initializeFromVirtualJoinTableRelationship(this); + } + + + // ********** misc ********** + + @Override + public JavaVirtualAssociationOverride getParent() { + return (JavaVirtualAssociationOverride) super.getParent(); + } + + public JavaVirtualAssociationOverride getAssociationOverride() { + return this.getParent(); + } + + public TypeMapping getTypeMapping() { + return this.getAssociationOverride().getContainer().getTypeMapping(); + } + + public Entity getEntity() { + TypeMapping typeMapping = this.getTypeMapping(); + return (typeMapping instanceof Entity) ? (Entity) typeMapping : null; + } + + public boolean isVirtual() { + return true; + } + + public RelationshipMapping getMapping() { + return this.getAssociationOverride().getMapping(); + } + + public Relationship resolveOverriddenRelationship() { + return this.getAssociationOverride().resolveOverriddenRelationship(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualUniqueConstraint.java new file mode 100644 index 0000000000..388f871257 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaVirtualUniqueConstraint.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +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.JavaVirtualUniqueConstraint; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaReadOnlyUniqueConstraint; + +public class GenericJavaVirtualUniqueConstraint + extends AbstractJavaReadOnlyUniqueConstraint + implements JavaVirtualUniqueConstraint +{ + protected final UniqueConstraint overriddenUniqueConstraint; + + + public GenericJavaVirtualUniqueConstraint(JavaJpaContextNode parent, UniqueConstraint overriddenUniqueConstraint) { + super(parent); + this.overriddenUniqueConstraint = overriddenUniqueConstraint; + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.syncColumnNames(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } + + + // ********** misc ********** + + public UniqueConstraint getOverriddenUniqueConstraint() { + return this.overriddenUniqueConstraint; + } + + @Override + protected Iterable<String> getResourceColumnNames() { + return this.overriddenUniqueConstraint.getColumnNames(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaConverter.java new file mode 100644 index 0000000000..3908130b3c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaConverter.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; +import org.eclipse.jpt.jpa.core.context.java.JavaConverter; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.resource.java.Annotation; + +public class NullJavaConverter + extends AbstractJavaJpaContextNode + implements JavaConverter +{ + public NullJavaConverter(JavaAttributeMapping parent) { + super(parent); + } + + @Override + public JavaAttributeMapping getParent() { + return (JavaAttributeMapping) super.getParent(); + } + + public Class<? extends Converter> getType() { + return null; + } + + public Annotation getConverterAnnotation() { + return null; + } + + public void dispose() { + // NOP + } + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinColumnRelationshipStrategy.java new file mode 100644 index 0000000000..61ba4bc7bc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinColumnRelationshipStrategy.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import java.util.ListIterator; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +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.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.db.Table; + +/** + * Used by + * {@link org.eclipse.jpt.jpa.core.internal.context.java.GenericJavaOneToManyRelationship#buildJoinColumnStrategy()} + * in a JPA 1.0 project. + */ +public class NullJavaJoinColumnRelationshipStrategy + extends AbstractJavaJpaContextNode + implements JavaJoinColumnRelationshipStrategy +{ + public NullJavaJoinColumnRelationshipStrategy(JavaJoinColumnRelationship parent) { + super(parent); + } + + + // ********** join columns ********** + + public ListIterator<JavaJoinColumn> joinColumns() { + return EmptyListIterator.<JavaJoinColumn>instance(); + } + + public int joinColumnsSize() { + return 0; + } + + + // ********** specified join columns ********** + + public ListIterator<JavaJoinColumn> specifiedJoinColumns() { + return EmptyListIterator.<JavaJoinColumn>instance(); + } + + public int specifiedJoinColumnsSize() { + return 0; + } + + public boolean hasSpecifiedJoinColumns() { + return false; + } + + public JavaJoinColumn getSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public JavaJoinColumn addSpecifiedJoinColumn() { + throw new UnsupportedOperationException(); + } + + public JavaJoinColumn addSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + throw new UnsupportedOperationException(); + } + + + // ********** default join column ********** + + public JavaJoinColumn getDefaultJoinColumn() { + return null; + } + + + // ********** misc ********** + + @Override + public JavaJoinColumnRelationship getParent() { + return (JavaJoinColumnRelationship) super.getParent(); + } + + public JavaJoinColumnRelationship getRelationship() { + return this.getParent(); + } + + protected RelationshipMapping getRelationshipMapping() { + return this.getRelationship().getMapping(); + } + + public String getTableName() { + return null; + } + + public TypeMapping getRelationshipSource() { + return this.getRelationshipMapping().getTypeMapping(); + } + + public TypeMapping getRelationshipTarget() { + return null; + } + + public boolean isTargetForeignKey() { + return false; + } + + public void initializeFrom(ReadOnlyJoinColumnRelationshipStrategy oldStrategy) { + // NOP + } + + public void initializeFromVirtual(ReadOnlyJoinColumnRelationshipStrategy oldStrategy) { + // NOP + } + + public void addStrategy() { + // NOP + } + + public void removeStrategy() { + // NOP + } + + public boolean isOverridable() { + return false; + } + + public boolean tableNameIsInvalid(String tableName) { + return true; + } + + public Table resolveDbTable(String tableName) { + return null; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + return null; + } + + public String getColumnTableNotValidDescription() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinTableRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinTableRelationshipStrategy.java new file mode 100644 index 0000000000..b5df2972f5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/NullJavaJoinTableRelationshipStrategy.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * 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.jpa1.context.java; + +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.JoinColumn.Owner; +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.JoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaJpaContextNode; +import org.eclipse.jpt.jpa.core.resource.java.JoinTableAnnotation; +import org.eclipse.jpt.jpa.db.Table; + +public class NullJavaJoinTableRelationshipStrategy + extends AbstractJavaJpaContextNode + implements JavaJoinTableRelationshipStrategy +{ + public NullJavaJoinTableRelationshipStrategy(JavaJoinTableRelationship parent) { + super(parent); + } + + + // ********** join table ********** + + public JavaJoinTable getJoinTable() { + return null; + } + + public JoinTableAnnotation getJoinTableAnnotation() { + return null; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange(CompilationUnit astRoot) { + throw new UnsupportedOperationException(); + } + + + // ********** misc ********** + + @Override + public JavaJoinTableRelationship getParent() { + return (JavaJoinTableRelationship) super.getParent(); + } + + public JavaJoinTableRelationship getRelationship() { + return this.getParent(); + } + + public void initializeFrom(ReadOnlyJoinTableRelationshipStrategy oldStrategy) { + // NOP + } + + public void initializeFromVirtual(ReadOnlyJoinTableRelationshipStrategy virtualStrategy) { + // NOP + } + + public String getTableName() { + return null; + } + + public Table resolveDbTable(String tableName) { + return null; + } + + public boolean tableNameIsInvalid(String tableName) { + return true; + } + + public String getColumnTableNotValidDescription() { + return null; + } + + public String getJoinTableDefaultName() { + return null; + } + + public void addStrategy() { + // NOP + } + + public void removeStrategy() { + // NOP + } + + public boolean isOverridable() { + return false; + } + + public boolean validatesAgainstDatabase() { + return false; + } + + public JptValidator buildJoinTableJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + throw new UnsupportedOperationException(); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + throw new UnsupportedOperationException(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmConverter.java new file mode 100644 index 0000000000..1c73603b0a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmConverter.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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmConverter; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlConvertibleMapping; + +public abstract class AbstractOrmConverter + extends AbstractOrmXmlContextNode + implements OrmConverter +{ + protected AbstractOrmConverter(OrmAttributeMapping parent) { + super(parent); + } + + + // ********** misc ********** + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + protected OrmAttributeMapping getAttributeMapping() { + return this.getParent(); + } + + protected XmlAttributeMapping getXmlAttributeMapping() { + return this.getAttributeMapping().getXmlAttributeMapping(); + } + + protected XmlConvertibleMapping getXmlConvertibleMapping() { + return (XmlConvertibleMapping) this.getXmlAttributeMapping(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverride.java new file mode 100644 index 0000000000..4494cddecc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverride.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.ReadOnlyOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualOverride; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmOverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOverride; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Specified <code>orm.xml</code> override + */ +public abstract class AbstractOrmOverride<C extends OrmOverrideContainer, X extends XmlOverride> + extends AbstractOrmXmlContextNode + implements OrmOverride +{ + protected final X xmlOverride; + + protected String name; + + + protected AbstractOrmOverride(C parent, X xmlOverride) { + super(parent); + this.xmlOverride = xmlOverride; + this.name = xmlOverride.getName(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setName_(this.xmlOverride.getName()); + } + + + // ********** name ********** + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.setName_(name); + this.xmlOverride.setName(name); + } + + protected void setName_(String name) { + String old = this.name; + this.name = name; + this.firePropertyChanged(NAME_PROPERTY, old, name); + } + + + // ********** specified/virtual ********** + + public boolean isVirtual() { + return false; + } + + public OrmVirtualOverride convertToVirtual() { + return this.getContainer().convertOverrideToVirtual(this); + } + + + // ********** misc ********** + + @Override + @SuppressWarnings("unchecked") + public C getParent() { + return (C) super.getParent(); + } + + public C getContainer() { + return this.getParent(); + } + + public X getXmlOverride() { + return this.xmlOverride; + } + + protected void initializeFrom(ReadOnlyOverride oldOverride) { + this.setName(oldOverride.getName()); + } + + protected void initializeFromVirtual(ReadOnlyOverride virtualOverride) { + this.setName(virtualOverride.getName()); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.buildValidator().validate(messages, reporter); + } + + protected JptValidator buildValidator() { + return this.getContainer().buildValidator(this, this.buildTextRangeResolver()); + } + + protected OverrideTextRangeResolver buildTextRangeResolver() { + return new OrmOverrideTextRangeResolver(this); + } + + public TextRange getValidationTextRange() { + TextRange textRange = this.xmlOverride.getValidationTextRange(); + return (textRange != null) ? textRange : this.getParent().getValidationTextRange(); + } + + public TextRange getNameTextRange() { + TextRange textRange = this.xmlOverride.getNameTextRange(); + return (textRange != null) ? textRange : this.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverrideContainer.java new file mode 100644 index 0000000000..b2d3ad9903 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmOverrideContainer.java @@ -0,0 +1,472 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterables.CompositeListIterable; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +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.common.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.Override_; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.VirtualOverride; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualOverride; +import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; +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.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOverride; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> override container + */ +public abstract class AbstractOrmOverrideContainer< + O extends OrmOverrideContainer.Owner, + R extends OrmReadOnlyOverride, + S extends OrmOverride, + V extends OrmVirtualOverride, + X extends XmlOverride + > + extends AbstractOrmXmlContextNode + implements OrmOverrideContainer +{ + // this can be null if the container is "read-only" (i.e. a "null" container) + protected final O owner; + + protected final Vector<S> specifiedOverrides = new Vector<S>(); + protected final SpecifiedOverrideContainerAdapter specifiedOverrideContainerAdapter = new SpecifiedOverrideContainerAdapter(); + + protected final Vector<V> virtualOverrides = new Vector<V>(); + protected final VirtualOverrideContainerAdapter virtualOverrideContainerAdapter = new VirtualOverrideContainerAdapter(); + + + protected AbstractOrmOverrideContainer(XmlContextNode parent, O owner) { + super(parent); + this.owner = owner; + this.initializeSpecifiedOverrides(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedOverrides(); + // the virtual overrides do not need a sync + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedOverrides()); + this.updateVirtualOverrides(); + } + + + // ********** overrides ********** + + public ListIterator<R> overrides() { + return this.getOverrides().iterator(); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getOverrides() { + return new CompositeListIterable<R>(this.getReadOnlySpecifiedOverrides(), this.getReadOnlyVirtualOverrides()); + } + + public int overridesSize() { + return this.specifiedOverrides.size() + this.virtualOverrides.size(); + } + + public R getOverrideNamed(String name) { + return this.selectOverrideNamed(this.getOverrides(), name); + } + + + // ********** override conversions ********** + + /** + * <em>Silently</em> add the new virtual override before removing the + * specified override, or the <em>update</em> will discover the missing + * virtual override and add it preemptively. + */ + public V convertOverrideToVirtual(Override_ override) { + if (override.isVirtual()) { + throw new IllegalArgumentException("Override is already virtual: " + override); //$NON-NLS-1$ + } + + @SuppressWarnings("unchecked") + S specifiedOverride = (S) override; + int virtualIndex = this.virtualOverrides.size(); + String overrideName = specifiedOverride.getName(); + V virtualOverride = null; + // make sure the specified override actually overrides something before building the virtual override + if (this.overrideWillBeVirtual(overrideName, specifiedOverride)) { + virtualOverride = this.buildVirtualOverride(overrideName); + this.virtualOverrides.add(virtualIndex, virtualOverride); + } + + this.removeSpecifiedOverride(specifiedOverride); // trigger update + + if (virtualOverride != null) { + this.fireItemAdded(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride); + } + return virtualOverride; + } + + /** + * Return whether the specified override name will be a + * <em>virtual</em> override when the specified specified override is + * removed from the container. The override name must be among the + * valid override names and it must not correspond to any of the + * remaining specified overrides. + */ + protected boolean overrideWillBeVirtual(String overrideName, S specifiedOverrideToBeRemoved) { + return CollectionTools.contains(this.allOverridableNames(), overrideName) && + (this.getSpecifiedOverrideNamed(overrideName, specifiedOverrideToBeRemoved) == null); + } + + /** + * <em>Silently</em> remove the virtual override and add the new specified + * override before naming the specified override, or the <em>update</em> + * will discover the dangling virtual override and remove it preemptively. + */ + public S convertOverrideToSpecified(VirtualOverride override) { + if ( ! override.isVirtual()) { + throw new IllegalArgumentException("Override is already specified: " + override); //$NON-NLS-1$ + } + + @SuppressWarnings("unchecked") + V virtualOverride = (V) override; + int virtualIndex = this.virtualOverrides.indexOf(virtualOverride); + this.virtualOverrides.remove(virtualIndex); + + int specifiedIndex = this.specifiedOverrides.size(); + X xmlOverride = this.buildXmlOverride(); + S specifiedOverride = this.buildSpecifiedOverride(xmlOverride); + this.specifiedOverrides.add(specifiedIndex, specifiedOverride); + this.owner.getXmlOverrides().add(specifiedIndex, xmlOverride); + + this.initializeSpecifiedOverride(specifiedOverride, virtualOverride); // trigger update + + this.fireItemRemoved(VIRTUAL_OVERRIDES_LIST, virtualIndex, virtualOverride); + this.fireItemAdded(SPECIFIED_OVERRIDES_LIST, specifiedIndex, specifiedOverride); + return specifiedOverride; + } + + protected abstract void initializeSpecifiedOverride(S specifiedOverride, V virtualOverride); + + + // ********** specified overrides ********** + + public ListIterator<S> specifiedOverrides() { + return this.getSpecifiedOverrides().iterator(); + } + + protected ListIterable<S> getSpecifiedOverrides() { + return new LiveCloneListIterable<S>(this.specifiedOverrides); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getReadOnlySpecifiedOverrides() { + // S should always be a subtype of R, but we can't enforce that in the + // class declaration... + return (ListIterable<R>) this.getSpecifiedOverrides(); + } + + public int specifiedOverridesSize() { + return this.specifiedOverrides.size(); + } + + public S getSpecifiedOverride(int index) { + return this.specifiedOverrides.get(index); + } + + public S getSpecifiedOverrideNamed(String name) { + return this.getSpecifiedOverrideNamed(name, null); + } + + @SuppressWarnings("unchecked") + protected S getSpecifiedOverrideNamed(String name, S exclude) { + return (S) this.selectOverrideNamed(this.getReadOnlySpecifiedOverrides(), name, exclude); + } + + protected S addSpecifiedOverride() { + return this.addSpecifiedOverride(this.specifiedOverrides.size()); + } + + protected S addSpecifiedOverride(int index) { + X xmlOverride = this.buildXmlOverride(); + S override = this.addSpecifiedOverride_(index, xmlOverride); + this.owner.getXmlOverrides().add(index, xmlOverride); + return override; + } + + protected abstract X buildXmlOverride(); + + protected void removeSpecifiedOverride(S override) { + this.removeSpecifiedOverride(this.specifiedOverrides.indexOf(override)); + } + + protected void removeSpecifiedOverride(int index) { + this.removeSpecifiedOverride_(index); + this.owner.getXmlOverrides().remove(index); + } + + protected void removeSpecifiedOverride_(int index) { + this.removeItemFromList(index, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + } + + public void moveSpecifiedOverride(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + this.owner.getXmlOverrides().move(targetIndex, sourceIndex); + } + + protected void initializeSpecifiedOverrides() { + for (X xmlOverride : this.getXmlOverrides()) { + this.specifiedOverrides.add(this.buildSpecifiedOverride(xmlOverride)); + } + } + + protected abstract S buildSpecifiedOverride(X xmlOverride); + + protected void syncSpecifiedOverrides() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedOverrideContainerAdapter); + } + + protected Iterable<X> getXmlOverrides() { + return (this.owner == null) ? EmptyIterable.<X>instance() : this.getXmlOverrides_(); + } + + /** + * pre-condition: {@link #owner} is not <code>null</code> + */ + protected abstract Iterable<X> getXmlOverrides_(); + + protected void moveSpecifiedOverride_(int index, S override) { + this.moveItemInList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + } + + protected S addSpecifiedOverride_(int index, X xmlOverride) { + S override = this.buildSpecifiedOverride(xmlOverride); + this.addItemToList(index, override, this.specifiedOverrides, SPECIFIED_OVERRIDES_LIST); + return override; + } + + protected void removeSpecifiedOverride_(S override) { + this.removeSpecifiedOverride_(this.specifiedOverrides.indexOf(override)); + } + + /** + * specified override container adapter + */ + protected class SpecifiedOverrideContainerAdapter + implements ContextContainerTools.Adapter<S, X> + { + public Iterable<S> getContextElements() { + return AbstractOrmOverrideContainer.this.getSpecifiedOverrides(); + } + public Iterable<X> getResourceElements() { + return AbstractOrmOverrideContainer.this.getXmlOverrides(); + } + @SuppressWarnings("unchecked") + public X getResourceElement(S contextElement) { + return (X) contextElement.getXmlOverride(); + } + public void moveContextElement(int index, S element) { + AbstractOrmOverrideContainer.this.moveSpecifiedOverride_(index, element); + } + public void addContextElement(int index, X resourceElement) { + AbstractOrmOverrideContainer.this.addSpecifiedOverride_(index, resourceElement); + } + public void removeContextElement(S element) { + AbstractOrmOverrideContainer.this.removeSpecifiedOverride_(element); + } + } + + + // ********** virtual overrides ********** + + public ListIterator<V> virtualOverrides() { + return this.getVirtualOverrides().iterator(); + } + + protected ListIterable<V> getVirtualOverrides() { + return new LiveCloneListIterable<V>(this.virtualOverrides); + } + + @SuppressWarnings("unchecked") + protected ListIterable<R> getReadOnlyVirtualOverrides() { + // V should always be a subtype of R, but we can't enforce that in the + // class declaration... + return (ListIterable<R>) this.getVirtualOverrides(); + } + + public int virtualOverridesSize() { + return this.virtualOverrides.size(); + } + + protected void updateVirtualOverrides() { + ContextContainerTools.update(this.virtualOverrideContainerAdapter); + } + + /** + * Return the overridable names that are not already in the list of + * specified overrides. + */ + protected Iterable<String> getVirtualOverrideNames() { + return CollectionTools.iterable(this.virtualOverrideNames()); + } + + protected Iterator<String> virtualOverrideNames() { + return new FilteringIterator<String>(this.allOverridableNames()) { + @Override + protected boolean accept(String name) { + return AbstractOrmOverrideContainer.this.overrideIsVirtual(name); + } + }; + } + + protected boolean overrideIsVirtual(String name) { + return this.getSpecifiedOverrideNamed(name) == null; + } + + protected void moveVirtualOverride(int index, V override) { + this.moveItemInList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + } + + protected V addVirtualOverride(int index, String name) { + V override = this.buildVirtualOverride(name); + this.addItemToList(index, override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + return override; + } + + protected abstract V buildVirtualOverride(String name); + + protected void removeVirtualOverride(V override) { + this.removeItemFromList(override, this.virtualOverrides, VIRTUAL_OVERRIDES_LIST); + } + + /** + * virtual override container adapter + * NB: the context override is matched with a resource override by name + */ + protected class VirtualOverrideContainerAdapter + implements ContextContainerTools.Adapter<V, String> + { + public Iterable<V> getContextElements() { + return AbstractOrmOverrideContainer.this.getVirtualOverrides(); + } + public Iterable<String> getResourceElements() { + return AbstractOrmOverrideContainer.this.getVirtualOverrideNames(); + } + public String getResourceElement(V contextElement) { + return contextElement.getName(); + } + public void moveContextElement(int index, V element) { + AbstractOrmOverrideContainer.this.moveVirtualOverride(index, element); + } + public void addContextElement(int index, String resourceElement) { + AbstractOrmOverrideContainer.this.addVirtualOverride(index, resourceElement); + } + public void removeContextElement(V element) { + AbstractOrmOverrideContainer.this.removeVirtualOverride(element); + } + } + + + // ********** misc ********** + + public TypeMapping getOverridableTypeMapping() { + return this.owner.getOverridableTypeMapping(); + } + + public TypeMapping getTypeMapping() { + return this.owner.getTypeMapping(); + } + + public Iterator<String> allOverridableNames() { + return (this.owner != null) ? this.owner.allOverridableNames() : EmptyIterator.<String>instance(); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.owner.tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.owner.candidateTableNames(); + } + + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + return this.owner.resolveDbTable(tableName); + } + + public String getDefaultTableName() { + return this.owner.getDefaultTableName(); + } + + public JptValidator buildValidator(Override_ override, OverrideTextRangeResolver textRangeResolver) { + return this.owner.buildValidator(override, this, textRangeResolver); + } + + public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner columnOwner, BaseColumnTextRangeResolver textRangeResolver) { + return this.owner.buildColumnValidator(override, column, columnOwner, textRangeResolver); + } + + protected R selectOverrideNamed(Iterable<R> overrides, String name) { + return this.selectOverrideNamed(overrides, name, null); + } + + protected R selectOverrideNamed(Iterable<R> overrides, String name, S exclude) { + for (R override : overrides) { + if (override == exclude) { + continue; // skip + } + if (this.valuesAreEqual(override.getName(), name)) { + return override; + } + } + return null; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + for (R override : this.getOverrides()) { + override.validate(messages, reporter); + } + } + + public TextRange getValidationTextRange() { + return (this.specifiedOverrides.size() > 0) ? + this.specifiedOverrides.get(0).getValidationTextRange() : + this.owner.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmVirtualOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmVirtualOverride.java new file mode 100644 index 0000000000..2a4dd9cd02 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/AbstractOrmVirtualOverride.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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualOverride; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; + +/** + * Virtual <code>orm.xml</code> override + */ +public abstract class AbstractOrmVirtualOverride<C extends OrmOverrideContainer> + extends AbstractOrmXmlContextNode + implements OrmVirtualOverride +{ + protected final String name; // never null + + + protected AbstractOrmVirtualOverride(C parent, String name) { + super(parent); + this.name = name; + } + + public String getName() { + return this.name; + } + + public boolean isVirtual() { + return true; + } + + public OrmOverride 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() { + return this.getParent().getValidationTextRange(); + } + + @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/jpa1/context/orm/GenericEntityMappings.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericEntityMappings.java new file mode 100644 index 0000000000..a6ae9ee62b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericEntityMappings.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmXml; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractEntityMappings; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEntityMappings; + +/** + * <code>orm.xml</code> file + * <br> + * <code>entity-mappings</code> element + */ +public class GenericEntityMappings + extends AbstractEntityMappings +{ + public GenericEntityMappings(OrmXml parent, XmlEntityMappings resource) { + super(parent, resource); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java new file mode 100644 index 0000000000..25b6eb44c7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverride.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2008, 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.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.ReadOnlyAssociationOverride; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmOverrideRelationship; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAssociationOverride; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * Specified <code>orm.xml</code> association override + */ +public class GenericOrmAssociationOverride + extends AbstractOrmOverride<OrmAssociationOverrideContainer, XmlAssociationOverride> + implements OrmAssociationOverride +{ + protected final OrmOverrideRelationship relationship; + + + public GenericOrmAssociationOverride(OrmAssociationOverrideContainer parent, XmlAssociationOverride xmlOverride) { + super(parent, xmlOverride); + this.relationship = this.buildRelationship(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.relationship.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.relationship.update(); + } + + + // ********** specified/virtual ********** + + @Override + public OrmVirtualAssociationOverride convertToVirtual() { + return (OrmVirtualAssociationOverride) super.convertToVirtual(); + } + + + // ********** relationship ********** + + public OrmOverrideRelationship getRelationship() { + return this.relationship; + } + + protected OrmOverrideRelationship buildRelationship() { + return this.getContextNodeFactory().buildOrmOverrideRelationship(this); + } + + + // ********** misc ********** + + public RelationshipMapping getMapping() { + return this.getContainer().getRelationshipMapping(this.name); + } + + public void initializeFrom(ReadOnlyAssociationOverride oldOverride) { + super.initializeFrom(oldOverride); + this.relationship.initializeFrom(oldOverride.getRelationship()); + } + + public void initializeFromVirtual(ReadOnlyAssociationOverride virtualOverride) { + super.initializeFromVirtual(virtualOverride); + this.relationship.initializeFromVirtual(virtualOverride.getRelationship()); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.relationship.validate(messages, reporter); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java new file mode 100644 index 0000000000..6b34106360 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAssociationOverrideContainer.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.jpa.core.context.AssociationOverride; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAssociationOverride; +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.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAssociationOverride; + +/** + * <code>orm.xml</code> association override container + */ +public class GenericOrmAssociationOverrideContainer + extends AbstractOrmOverrideContainer< + OrmAssociationOverrideContainer.Owner, + OrmReadOnlyAssociationOverride, + OrmAssociationOverride, + OrmVirtualAssociationOverride, + XmlAssociationOverride + > + implements OrmAssociationOverrideContainer +{ + public GenericOrmAssociationOverrideContainer(XmlContextNode parent, OrmAssociationOverrideContainer.Owner owner) { + super(parent, owner); + } + + + public RelationshipMapping getRelationshipMapping(String attributeName) { + return MappingTools.getRelationshipMapping(attributeName, this.owner.getOverridableTypeMapping()); + } + + public Relationship resolveOverriddenRelationship(String associationOverrideName) { + return this.owner.resolveOverriddenRelationship(associationOverrideName); + } + + public JptValidator buildJoinTableJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner columnOwner, JoinColumnTextRangeResolver textRangeResolver) { + return this.owner.buildJoinTableJoinColumnValidator(override, column, columnOwner, textRangeResolver); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, JoinColumn.Owner columnOwner, JoinColumnTextRangeResolver textRangeResolver) { + return this.owner.buildJoinTableInverseJoinColumnValidator(override, column, columnOwner, textRangeResolver); + } + + public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) { + return this.owner.buildTableValidator(override, table, textRangeResolver); + } + + @Override + protected Iterable<XmlAssociationOverride> getXmlOverrides_() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlAssociationOverride>(this.owner.getXmlOverrides()); + } + + @Override + protected XmlAssociationOverride buildXmlOverride() { + return OrmFactory.eINSTANCE.createXmlAssociationOverride(); + } + + @Override + protected OrmAssociationOverride buildSpecifiedOverride(XmlAssociationOverride xmlOverride) { + return this.getContextNodeFactory().buildOrmAssociationOverride(this, xmlOverride); + } + + @Override + protected void initializeSpecifiedOverride(OrmAssociationOverride specifiedOverride, OrmVirtualAssociationOverride virtualOverride) { + specifiedOverride.initializeFromVirtual(virtualOverride); + } + + @Override + protected OrmVirtualAssociationOverride buildVirtualOverride(String name) { + return this.getContextNodeFactory().buildOrmVirtualAssociationOverride(this, name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java new file mode 100644 index 0000000000..9e6b30c0dc --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverride.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.jpa.core.context.BaseColumn; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyAttributeOverride; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAttributeOverride; +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.validation.DefaultJpaValidationMessages; +import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeOverride; +import org.eclipse.jpt.jpa.core.resource.orm.XmlColumn; +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; + +/** + * Specified <code>orm.xml</code> attribute override + */ +public class GenericOrmAttributeOverride + extends AbstractOrmOverride<OrmAttributeOverrideContainer, XmlAttributeOverride> + implements OrmAttributeOverride, OrmColumn.Owner +{ + protected final OrmColumn column; + + + public GenericOrmAttributeOverride(OrmAttributeOverrideContainer parent, XmlAttributeOverride xmlOverride) { + super(parent, xmlOverride); + this.column = this.buildColumn(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.column.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.column.update(); + } + + + // ********** specified/virtual ********** + + @Override + public OrmVirtualAttributeOverride convertToVirtual() { + return (OrmVirtualAttributeOverride) super.convertToVirtual(); + } + + + // ********** column ********** + + public OrmColumn getColumn() { + return this.column; + } + + protected OrmColumn buildColumn() { + return this.getContextNodeFactory().buildOrmColumn(this, this); + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyAttributeOverride oldOverride) { + super.initializeFrom(oldOverride); + this.column.initializeFrom(oldOverride.getColumn()); + } + + public void initializeFromVirtual(ReadOnlyAttributeOverride oldOverride) { + super.initializeFromVirtual(oldOverride); + this.column.initializeFromVirtual(oldOverride.getColumn()); + } + + + // ********** column owner implementation ********** + + public TypeMapping getTypeMapping() { + return this.getContainer().getTypeMapping(); + } + + public String getDefaultTableName() { + return this.getContainer().getDefaultTableName(); + } + + public Table resolveDbTable(String tableName) { + return this.getContainer().resolveDbTable(tableName); + } + + public String getDefaultColumnName() { + return this.name; + } + + public JptValidator buildColumnValidator(NamedColumn col, NamedColumnTextRangeResolver textRangeResolver) { + return this.getContainer().buildColumnValidator(this, (BaseColumn) col, this, (BaseColumnTextRangeResolver) textRangeResolver); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.getContainer().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.getContainer().candidateTableNames(); + } + + public XmlColumn getXmlColumn() { + return this.getXmlOverride().getColumn(); + } + + public XmlColumn buildXmlColumn() { + XmlColumn xmlColumn = OrmFactory.eINSTANCE.createXmlColumn(); + this.getXmlOverride().setColumn(xmlColumn); + return xmlColumn; + } + + public void removeXmlColumn() { + this.getXmlOverride().setColumn(null); + } + + + // ********** mapped by relationship ********** + + protected boolean isMappedByRelationship() { + return CollectionTools.contains(this.getMappedByRelationshipAttributeNames(), this.buildQualifier()); + } + + protected Iterable<String> getMappedByRelationshipAttributeNames() { + return TypeMappingTools.getMappedByRelationshipAttributeNames(this.getTypeMapping()); + } + + /** + * overridable names are (usually?) qualified with a container mapping, + * which may also be the one mapped by a relationship + */ + protected String buildQualifier() { + if (this.name == null) { + return null; + } + int index = this.name.indexOf('.'); + return (index == -1) ? this.name : this.name.substring(0, index); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + // [JPA 2.0] if the column is specified, or if the override is not mapped by a relationship, + // then the column is validated. + // (In JPA 1.0, the column will always be validated, since the override is never mapped by a + // relationship) + if (this.xmlColumnIsSpecified() || ! this.isMappedByRelationship()) { + this.column.validate(messages, reporter); + } + + // [JPA 2.0] if the override is mapped by a relationship, then that actually is in itself + // a validation error + // (We prevent implied overrides that are mapped by a relationship ... hopefully) + // (In JPA 1.0, this will never occur) + if (this.isMappedByRelationship()) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ATTRIBUTE_OVERRIDE_MAPPED_BY_RELATIONSHIP_AND_SPECIFIED, + EMPTY_STRING_ARRAY, + this, + this.getValidationTextRange() + ) + ); + } + } + + protected boolean xmlColumnIsSpecified() { + return this.getXmlColumn() != null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java new file mode 100644 index 0000000000..7501968550 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmAttributeOverrideContainer.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyAttributeOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAttributeOverride; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeOverride; + +/** + * <code>orm.xml</code> attribute override container + */ +public class GenericOrmAttributeOverrideContainer + extends AbstractOrmOverrideContainer< + OrmAttributeOverrideContainer.Owner, + OrmReadOnlyAttributeOverride, + OrmAttributeOverride, + OrmVirtualAttributeOverride, + XmlAttributeOverride + > + implements OrmAttributeOverrideContainer +{ + public GenericOrmAttributeOverrideContainer(XmlContextNode parent, OrmAttributeOverrideContainer.Owner owner) { + super(parent, owner); + } + + + public Column resolveOverriddenColumn(String attributeName) { + return (attributeName == null) ? null : this.owner.resolveOverriddenColumn(attributeName); + } + + @Override + protected Iterable<XmlAttributeOverride> getXmlOverrides_() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlAttributeOverride>(this.owner.getXmlOverrides()); + } + + @Override + protected XmlAttributeOverride buildXmlOverride() { + return OrmFactory.eINSTANCE.createXmlAttributeOverride(); + } + + @Override + protected OrmAttributeOverride buildSpecifiedOverride(XmlAttributeOverride xmlOverride) { + return this.getContextNodeFactory().buildOrmAttributeOverride(this, xmlOverride); + } + + public void initializeFrom(OrmAttributeOverrideContainer oldContainer) { + for (OrmAttributeOverride oldOverride : CollectionTools.iterable(oldContainer.specifiedOverrides())) { + this.addSpecifiedOverride().initializeFrom(oldOverride); + } + } + + @Override + protected void initializeSpecifiedOverride(OrmAttributeOverride specifiedOverride, OrmVirtualAttributeOverride virtualOverride) { + specifiedOverride.initializeFromVirtual(virtualOverride); + } + + @Override + protected OrmVirtualAttributeOverride buildVirtualOverride(String name) { + return this.getContextNodeFactory().buildOrmVirtualAttributeOverride(this, name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java new file mode 100644 index 0000000000..99f763d272 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmBasicMapping.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmBasicMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlBasic; + +/** + * <code>orm.xml</code> basic mapping + */ +public class GenericOrmBasicMapping + extends AbstractOrmBasicMapping<XmlBasic> +{ + public GenericOrmBasicMapping(OrmPersistentAttribute parent, XmlBasic xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmCascade.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmCascade.java new file mode 100644 index 0000000000..f27fde2d17 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmCascade.java @@ -0,0 +1,303 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Cascade; +import org.eclipse.jpt.jpa.core.context.orm.OrmRelationshipMapping; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmRelationshipMapping; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.jpa2.context.Cascade2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmCascade2_0; +import org.eclipse.jpt.jpa.core.resource.orm.AbstractXmlRelationshipMapping; +import org.eclipse.jpt.jpa.core.resource.orm.CascadeType; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; + +public class GenericOrmCascade + extends AbstractOrmXmlContextNode + implements OrmCascade2_0 +{ + protected boolean all; + + protected boolean persist; + + protected boolean merge; + + protected boolean remove; + + protected boolean refresh; + + /* JPA 2.0 */ + protected boolean detach; + + + /** + * This is built directly by the mapping implementation; as opposed to via + * a platform-specific factory. + * @see AbstractOrmRelationshipMapping#buildCascade() + */ + public GenericOrmCascade(OrmRelationshipMapping parent) { + super(parent); + this.all = this.buildAll(); + this.persist = this.buildPersist(); + this.merge = this.buildMerge(); + this.remove = this.buildRemove(); + this.refresh = this.buildRefresh(); + this.detach = this.buildDetach(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setAll_(this.buildAll()); + this.setPersist_(this.buildPersist()); + this.setMerge_(this.buildMerge()); + this.setRemove_(this.buildRemove()); + this.setRefresh_(this.buildRefresh()); + this.setDetach_(this.buildDetach()); + } + + + // ********** all ********** + + public boolean isAll() { + return this.all; + } + + public void setAll(boolean all) { + if (this.all != all) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setAll_(all); + xmlCascade.setCascadeAll(all); + this.removeXmlCascadeIfUnset(); + } + } + + protected void setAll_(boolean all) { + boolean old = this.all; + this.all = all; + this.firePropertyChanged(ALL_PROPERTY, old, all); + } + + protected boolean buildAll() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadeAll(); + } + + + // ********** persist ********** + + public boolean isPersist() { + return this.persist; + } + + public void setPersist(boolean persist) { + if (this.persist != persist) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setPersist_(persist); + xmlCascade.setCascadePersist(persist); + this.removeXmlCascadeIfUnset(); + } + } + + protected boolean setPersist_(boolean persist) { + boolean old = this.persist; + this.persist = persist; + return this.firePropertyChanged(PERSIST_PROPERTY, old, persist); + } + + protected boolean buildPersist() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadePersist(); + } + + + // ********** merge ********** + + public boolean isMerge() { + return this.merge; + } + + public void setMerge(boolean merge) { + if (this.merge != merge) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setMerge_(merge); + xmlCascade.setCascadeMerge(merge); + this.removeXmlCascadeIfUnset(); + } + } + + protected boolean setMerge_(boolean merge) { + boolean old = this.merge; + this.merge = merge; + return this.firePropertyChanged(MERGE_PROPERTY, old, merge); + } + + protected boolean buildMerge() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadeMerge(); + } + + + // ********** remove ********** + + public boolean isRemove() { + return this.remove; + } + + public void setRemove(boolean remove) { + if (this.remove != remove) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setRemove_(remove); + xmlCascade.setCascadeRemove(remove); + this.removeXmlCascadeIfUnset(); + } + } + + protected boolean setRemove_(boolean remove) { + boolean old = this.remove; + this.remove = remove; + return this.firePropertyChanged(REMOVE_PROPERTY, old, remove); + } + + protected boolean buildRemove() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadeRemove(); + } + + + // ********** refresh ********** + + public boolean isRefresh() { + return this.refresh; + } + + public void setRefresh(boolean refresh) { + if (this.refresh != refresh) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setRefresh_(refresh); + xmlCascade.setCascadeRefresh(refresh); + this.removeXmlCascadeIfUnset(); + } + } + + protected boolean setRefresh_(boolean refresh) { + boolean old = this.refresh; + this.refresh = refresh; + return this.firePropertyChanged(REFRESH_PROPERTY, old, refresh); + } + + protected boolean buildRefresh() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadeRefresh(); + } + + + // ********** detach ********** + + public boolean isDetach() { + return this.detach; + } + + public void setDetach(boolean detach) { + if (this.detach != detach) { + CascadeType xmlCascade = this.getXmlCascadeForUpdate(); + this.setDetach_(detach); + xmlCascade.setCascadeDetach(detach); + this.removeXmlCascadeIfUnset(); + } + } + + protected boolean setDetach_(boolean detach) { + boolean old = this.detach; + this.detach = detach; + return this.firePropertyChanged(DETACH_PROPERTY, old, detach); + } + + protected boolean buildDetach() { + return this.isJpa2_0Compatible() && this.buildDetach_(); + } + + protected boolean buildDetach_() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) && xmlCascade.isCascadeDetach(); + } + + + // ********** XML cascade ********** + + /** + * Return <code>null</code> if XML cascade does not exists. + */ + protected CascadeType getXmlCascade() { + return this.getXmlRelationshipMapping().getCascade(); + } + + /** + * Build the XML cascade if it does not exist. + */ + protected CascadeType getXmlCascadeForUpdate() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) ? xmlCascade : this.buildXmlCascade(); + } + + protected CascadeType buildXmlCascade() { + CascadeType xmlCascade = OrmFactory.eINSTANCE.createCascadeType(); + this.getXmlRelationshipMapping().setCascade(xmlCascade); + return xmlCascade; + } + + protected void removeXmlCascadeIfUnset() { + if (this.getXmlCascade().isUnset()) { + this.removeXmlCascade(); + } + } + + protected void removeXmlCascade() { + this.getXmlRelationshipMapping().setCascade(null); + } + + + // ********** misc ********** + + @Override + public OrmRelationshipMapping getParent() { + return (OrmRelationshipMapping) super.getParent(); + } + + protected OrmRelationshipMapping getRelationshipMapping() { + return this.getParent(); + } + + protected AbstractXmlRelationshipMapping getXmlRelationshipMapping() { + return this.getRelationshipMapping().getXmlAttributeMapping(); + } + + public void initializeFrom(Cascade oldCascade) { + this.setAll(oldCascade.isAll()); + this.setPersist(oldCascade.isPersist()); + this.setMerge(oldCascade.isMerge()); + this.setRemove(oldCascade.isRemove()); + this.setRefresh(oldCascade.isRefresh()); + if (this.isJpa2_0Compatible()) { + this.setDetach(((Cascade2_0) oldCascade).isDetach()); + } + } + + public TextRange getValidationTextRange() { + CascadeType xmlCascade = this.getXmlCascade(); + return (xmlCascade != null) ? + xmlCascade.getValidationTextRange() : + this.getRelationshipMapping().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmColumn.java new file mode 100644 index 0000000000..6e254476eb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmColumn.java @@ -0,0 +1,188 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.ReadOnlyColumn; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmBaseColumn; +import org.eclipse.jpt.jpa.core.resource.orm.XmlColumn; + +/** + * <code>orm.xml</code> column + */ +public class GenericOrmColumn + extends AbstractOrmBaseColumn<XmlColumn, OrmColumn.Owner> + implements OrmColumn +{ + // TODO defaults from java for all of these settings + protected Integer specifiedLength; + + protected Integer specifiedPrecision; + + protected Integer specifiedScale; + + + public GenericOrmColumn(XmlContextNode parent, OrmColumn.Owner owner) { + super(parent, owner); + this.specifiedLength = this.buildSpecifiedLength(); + this.specifiedPrecision = this.buildSpecifiedPrecision(); + this.specifiedScale = this.buildSpecifiedScale(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedLength_(this.buildSpecifiedLength()); + this.setSpecifiedPrecision_(this.buildSpecifiedPrecision()); + this.setSpecifiedScale_(this.buildSpecifiedScale()); + } + + + // ********** XML column ********** + + @Override + public XmlColumn getXmlColumn() { + return this.owner.getXmlColumn(); + } + + @Override + protected XmlColumn buildXmlColumn() { + return this.owner.buildXmlColumn(); + } + + @Override + protected void removeXmlColumn() { + this.owner.removeXmlColumn(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.getDefaultLength(); + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer length) { + if (this.valuesAreDifferent(this.specifiedLength, length)) { + XmlColumn xmlColumn = this.getXmlColumnForUpdate(); + this.setSpecifiedLength_(length); + xmlColumn.setLength(length); + this.removeXmlColumnIfUnset(); + } + } + + protected void setSpecifiedLength_(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + XmlColumn xmlColumn = this.getXmlColumn(); + return (xmlColumn == null) ? null : xmlColumn.getLength(); + } + + public int getDefaultLength() { + return DEFAULT_LENGTH; + } + + + // ********** precision ********** + + public int getPrecision() { + return (this.specifiedPrecision != null) ? this.specifiedPrecision.intValue() : this.getDefaultPrecision(); + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + public void setSpecifiedPrecision(Integer precision) { + if (this.valuesAreDifferent(this.specifiedPrecision, precision)) { + XmlColumn xmlColumn = this.getXmlColumnForUpdate(); + this.setSpecifiedPrecision_(precision); + xmlColumn.setPrecision(precision); + this.removeXmlColumnIfUnset(); + } + } + + protected void setSpecifiedPrecision_(Integer precision) { + Integer old = this.specifiedPrecision; + this.specifiedPrecision = precision; + this.firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, old, precision); + } + + protected Integer buildSpecifiedPrecision() { + XmlColumn xmlColumn = this.getXmlColumn(); + return (xmlColumn == null) ? null : xmlColumn.getPrecision(); + } + + public int getDefaultPrecision() { + return DEFAULT_PRECISION; + } + + + // ********** scale ********** + + public int getScale() { + return (this.specifiedScale != null) ? this.specifiedScale.intValue() : this.getDefaultScale(); + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + public void setSpecifiedScale(Integer scale) { + if (this.valuesAreDifferent(this.specifiedScale, scale)) { + XmlColumn xmlColumn = this.getXmlColumnForUpdate(); + this.setSpecifiedScale_(scale); + xmlColumn.setScale(scale); + this.removeXmlColumnIfUnset(); + } + } + + protected void setSpecifiedScale_(Integer scale) { + Integer old = this.specifiedScale; + this.specifiedScale = scale; + this.firePropertyChanged(SPECIFIED_SCALE_PROPERTY, old, scale); + } + + protected Integer buildSpecifiedScale() { + XmlColumn xmlColumn = this.getXmlColumn(); + return (xmlColumn == null) ? null : xmlColumn.getScale(); + } + + public int getDefaultScale() { + return DEFAULT_SCALE; + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyColumn oldColumn) { + super.initializeFrom(oldColumn); + this.setSpecifiedLength(oldColumn.getSpecifiedLength()); + this.setSpecifiedPrecision(oldColumn.getSpecifiedPrecision()); + this.setSpecifiedScale(oldColumn.getSpecifiedScale()); + } + + public void initializeFromVirtual(ReadOnlyColumn virtualColumn) { + super.initializeFromVirtual(virtualColumn); + // ignore other settings? + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java new file mode 100644 index 0000000000..be90386975 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmDiscriminatorColumn.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.DiscriminatorType; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmDiscriminatorColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmNamedColumn; +import org.eclipse.jpt.jpa.core.resource.orm.XmlDiscriminatorColumn; + +/** + * <code>orm.xml</code> discriminator column + */ +public class GenericOrmDiscriminatorColumn + extends AbstractOrmNamedColumn<XmlDiscriminatorColumn, OrmDiscriminatorColumn.Owner> + implements OrmDiscriminatorColumn +{ + protected DiscriminatorType specifiedDiscriminatorType; + protected DiscriminatorType defaultDiscriminatorType; + + protected Integer specifiedLength; + protected int defaultLength; + + + public GenericOrmDiscriminatorColumn(XmlContextNode parent, OrmDiscriminatorColumn.Owner owner) { + super(parent, owner); + this.specifiedDiscriminatorType = this.buildSpecifiedDiscriminatorType(); + this.specifiedLength = this.buildSpecifiedLength(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedDiscriminatorType_(this.buildSpecifiedDiscriminatorType()); + this.setSpecifiedLength_(this.buildSpecifiedLength()); + } + + @Override + public void update() { + super.update(); + this.setDefaultDiscriminatorType(this.buildDefaultDiscriminatorType()); + this.setDefaultLength(this.buildDefaultLength()); + } + + + // ********** XML column ********** + + @Override + public XmlDiscriminatorColumn getXmlColumn() { + return this.owner.getXmlColumn(); + } + + @Override + protected XmlDiscriminatorColumn buildXmlColumn() { + return this.owner.buildXmlColumn(); + } + + @Override + protected void removeXmlColumn() { + this.owner.removeXmlColumn(); + } + + + // ********** discriminator type ********** + + public DiscriminatorType getDiscriminatorType() { + return (this.specifiedDiscriminatorType != null) ? this.specifiedDiscriminatorType : this.defaultDiscriminatorType; + } + + public DiscriminatorType getSpecifiedDiscriminatorType() { + return this.specifiedDiscriminatorType; + } + + public void setSpecifiedDiscriminatorType(DiscriminatorType discriminatorType) { + if (this.valuesAreDifferent(this.specifiedDiscriminatorType, discriminatorType)) { + XmlDiscriminatorColumn xmlColumn = this.getXmlColumnForUpdate(); + this.setSpecifiedDiscriminatorType_(discriminatorType); + xmlColumn.setDiscriminatorType(DiscriminatorType.toOrmResourceModel(discriminatorType)); + this.removeXmlColumnIfUnset(); + } + } + + protected void setSpecifiedDiscriminatorType_(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.specifiedDiscriminatorType; + this.specifiedDiscriminatorType = discriminatorType; + this.firePropertyChanged(SPECIFIED_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + protected DiscriminatorType buildSpecifiedDiscriminatorType() { + XmlDiscriminatorColumn xmlColumn = this.getXmlColumn(); + return (xmlColumn == null) ? null : DiscriminatorType.fromOrmResourceModel(xmlColumn.getDiscriminatorType()); + } + + public DiscriminatorType getDefaultDiscriminatorType() { + return this.defaultDiscriminatorType; + } + + protected void setDefaultDiscriminatorType(DiscriminatorType discriminatorType) { + DiscriminatorType old = this.defaultDiscriminatorType; + this.defaultDiscriminatorType = discriminatorType; + this.firePropertyChanged(DEFAULT_DISCRIMINATOR_TYPE_PROPERTY, old, discriminatorType); + } + + protected DiscriminatorType buildDefaultDiscriminatorType() { + return this.owner.getDefaultDiscriminatorType(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.defaultLength; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + public void setSpecifiedLength(Integer length) { + if (this.valuesAreDifferent(this.specifiedLength, length)) { + XmlDiscriminatorColumn xmlColumn = this.getXmlColumnForUpdate(); + this.setSpecifiedLength_(length); + xmlColumn.setLength(length); + this.removeXmlColumnIfUnset(); + } + } + + protected void setSpecifiedLength_(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + XmlDiscriminatorColumn xmlColumn = this.getXmlColumn(); + return (xmlColumn == null) ? null : xmlColumn.getLength(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int defaultLength) { + int old = this.defaultLength; + this.defaultLength = defaultLength; + this.firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, defaultLength); + } + + protected int buildDefaultLength() { + return this.owner.getDefaultLength(); + } + + + // ********** validation ********** + + public boolean isResourceSpecified() { + return this.getXmlColumn() != null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java new file mode 100644 index 0000000000..9ecf827277 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddable.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2006, 2009 Oracle. All rights reserved. This + * program and the accompanying materials are made available under the terms of + * the Eclipse Public License v1.0 which accompanies this distribution, and is + * available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: Oracle. - initial API and implementation + *******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.common.utility.internal.ArrayTools; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmEmbeddable; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.GenericJavaEmbeddable; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEmbeddable; + +/** + * <code>orm.xml</code> embeddable type mapping + */ +public class GenericOrmEmbeddable + extends AbstractOrmEmbeddable<XmlEmbeddable> +{ + public GenericOrmEmbeddable(OrmPersistentType parent, XmlEmbeddable resourceMapping) { + super(parent, resourceMapping); + } + + @Override + public boolean attributeMappingKeyAllowed(String attributeMappingKey) { + return ArrayTools.contains(GenericJavaEmbeddable.ALLOWED_ATTRIBUTE_MAPPING_KEYS, attributeMappingKey); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java new file mode 100644 index 0000000000..b8fad23d1c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedIdMapping.java @@ -0,0 +1,180 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.common.utility.internal.iterators.FilteringIterator; +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmEmbeddedIdMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.TypeMappingTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmBaseEmbeddedMapping; +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.EmbeddedIdMapping2_0; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEmbeddedId; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> embedded ID mapping + */ +public class GenericOrmEmbeddedIdMapping + extends AbstractOrmBaseEmbeddedMapping<XmlEmbeddedId> + implements EmbeddedIdMapping2_0, OrmEmbeddedIdMapping +{ + /* JPA 2.0 feature - a relationship may map this embedded ID */ + protected boolean mappedByRelationship; + + + public GenericOrmEmbeddedIdMapping(OrmPersistentAttribute parent, XmlEmbeddedId xmlMapping) { + super(parent, xmlMapping); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.setMappedByRelationship(this.buildMappedByRelationship()); + } + + + // ********** mapped by relationship ********** + + public boolean isMappedByRelationship() { + return this.mappedByRelationship; + } + + protected void setMappedByRelationship(boolean value) { + boolean old = this.mappedByRelationship; + this.mappedByRelationship = value; + this.firePropertyChanged(MAPPED_BY_RELATIONSHIP_PROPERTY, old, value); + } + + protected boolean buildMappedByRelationship() { + return this.isJpa2_0Compatible() && this.buildMappedByRelationship_(); + } + + protected boolean buildMappedByRelationship_() { + return CollectionTools.contains(this.getMappedByRelationshipAttributeNames(), this.name); + } + + protected Iterable<String> getMappedByRelationshipAttributeNames() { + return TypeMappingTools.getMappedByRelationshipAttributeNames(this.getTypeMapping()); + } + + + // ********** misc ********** + + public String getKey() { + return MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY; + } + + public int getXmlSequence() { + return 10; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmEmbeddedIdMapping(this); + } + + public void addXmlAttributeMappingTo(Attributes xmlAttributes) { + xmlAttributes.getEmbeddedIds().add(this.xmlAttributeMapping); + } + + public void removeXmlAttributeMappingFrom(Attributes xmlAttributes) { + xmlAttributes.getEmbeddedIds().remove(this.xmlAttributeMapping); + } + + @Override + protected Iterator<String> embeddableOverridableAttributeMappingNames() { + return this.mappedByRelationship ? + EmptyIterator.<String>instance() : + super.embeddableOverridableAttributeMappingNames(); + } + + @Override + protected OrmAttributeOverrideContainer.Owner buildAttributeOverrideContainerOwner() { + return new AttributeOverrideContainerOwner(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + // [JPA 2.0] if the embedded id is mapped by a relationship, then any specified + // attribute overrides are in error + // (in JPA 1.0, this will obviously never be reached) + if (this.mappedByRelationship + && (this.attributeOverrideContainer.specifiedOverridesSize() > 0)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.EMBEDDED_ID_MAPPING_MAPPED_BY_RELATIONSHIP_AND_ATTRIBUTE_OVERRIDES_SPECIFIED, + EMPTY_STRING_ARRAY, + this.attributeOverrideContainer, + this.attributeOverrideContainer.getValidationTextRange() + ) + ); + } + } + + + // ********** attribute override container owner ********* + + protected class AttributeOverrideContainerOwner + extends AbstractOrmBaseEmbeddedMapping<XmlEmbeddedId>.AttributeOverrideContainerOwner + { + @Override + public Iterator<String> allOverridableNames() { + return GenericOrmEmbeddedIdMapping.this.isMappedByRelationship() ? + EmptyIterator.<String>instance() : + super.allOverridableNames(); + } + + /** + * pre-condition: type mapping is not <code>null</code> + */ + @Override + protected Iterator<String> allOverridableAttributeNames_(TypeMapping typeMapping) { + final Set<String> mappedByRelationshipAttributeNames = this.buildMappedByRelationshipAttributeNames(); + if (mappedByRelationshipAttributeNames.isEmpty()) { + return super.allOverridableAttributeNames_(typeMapping); + } + return new FilteringIterator<String>(super.allOverridableAttributeNames_(typeMapping)) { + @Override + protected boolean accept(String attributeName) { + // overridable names are (usually?) qualified with a container mapping, + // which may also be the one mapped by a relationship + int dotIndex = attributeName.indexOf('.'); + String qualifier = (dotIndex > 0) ? attributeName.substring(0, dotIndex) : attributeName; + return ! mappedByRelationshipAttributeNames.contains(qualifier); + } + }; + } + + protected Set<String> buildMappedByRelationshipAttributeNames() { + return CollectionTools.set(GenericOrmEmbeddedIdMapping.this.getMappedByRelationshipAttributeNames()); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java new file mode 100644 index 0000000000..aa025b16e4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEmbeddedMapping.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.emf.common.util.EList; +import org.eclipse.jpt.common.core.utility.TextRange; +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.FilteringIterator; +import org.eclipse.jpt.common.utility.internal.iterators.SubIteratorWrapper; +import org.eclipse.jpt.jpa.core.MappingKeys; +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.BaseColumn; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.JoinTable; +import org.eclipse.jpt.jpa.core.context.OverrideContainer; +import org.eclipse.jpt.jpa.core.context.Override_; +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +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.JavaAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMapping; +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.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.OverrideTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmBaseEmbeddedMapping; +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.EmbeddableOverrideDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.JoinTableTableDescriptionProvider; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaEmbeddedMapping2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmEmbeddedMapping2_0; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAssociationOverride; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEmbedded; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> embedded mapping + */ +public class GenericOrmEmbeddedMapping + extends AbstractOrmBaseEmbeddedMapping<XmlEmbedded> + implements OrmEmbeddedMapping2_0 +{ + protected final OrmAssociationOverrideContainer associationOverrideContainer; + + + public GenericOrmEmbeddedMapping(OrmPersistentAttribute parent, XmlEmbedded xmlMapping) { + super(parent, xmlMapping); + this.associationOverrideContainer = this.buildAssociationOverrideContainer(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.associationOverrideContainer.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.associationOverrideContainer.update(); + } + + + // ********** association override container ********** + + public OrmAssociationOverrideContainer getAssociationOverrideContainer() { + return this.associationOverrideContainer; + } + + protected OrmAssociationOverrideContainer buildAssociationOverrideContainer() { + return this.isJpa2_0Compatible() ? + this.getContextNodeFactory2_0().buildOrmAssociationOverrideContainer(this, this.buildAssociationOverrideContainerOwner()) : + new GenericOrmAssociationOverrideContainer(this, null); + } + + protected OrmAssociationOverrideContainer.Owner buildAssociationOverrideContainerOwner() { + return new AssociationOverrideContainerOwner(); + } + + + // ********** embedded mappings ********** + + /** + * This is only to build the choices for a "mapped by" setting in a + * relationship mapping. JPA 2.0 does not support relationship mappings + * in an embedded ID class; so we only put this logic here. + */ + @Override + @SuppressWarnings("unchecked") + public Iterator<String> allMappingNames() { + return this.isJpa2_0Compatible() ? + new CompositeIterator<String>(super.allMappingNames(), this.allEmbeddableAttributeMappingNames()) : + super.allMappingNames(); + } + + protected Iterator<String> allEmbeddableAttributeMappingNames() { + return this.qualifiedEmbeddableOverridableMappingNames(AttributeMappingTools.ALL_MAPPING_NAMES_TRANSFORMER); + } + + protected Iterator<RelationshipMapping> allOverridableAssociations() { + return (this.targetEmbeddable != null) ? + new SubIteratorWrapper<AttributeMapping, RelationshipMapping>(this.allOverridableAssociations_()) : + EmptyIterator.<RelationshipMapping>instance(); + } + + protected Iterator<AttributeMapping> allOverridableAssociations_() { + return new FilteringIterator<AttributeMapping>(this.targetEmbeddable.attributeMappings()) { + @Override + protected boolean accept(AttributeMapping attributeMapping) { + return attributeMapping.isOverridableAssociationMapping(); + } + }; + } + + @Override + public AttributeMapping resolveAttributeMapping(String attributeName) { + AttributeMapping resolvedMapping = super.resolveAttributeMapping(attributeName); + if (resolvedMapping != null) { + return resolvedMapping; + } + return this.isJpa2_0Compatible() ? this.resolveAttributeMapping_(attributeName) : null; + } + + protected AttributeMapping resolveAttributeMapping_(String attributeName) { + attributeName = this.unqualify(attributeName); + if (attributeName == null) { + return null; + } + // recurse into the embeddable mappings + for (AttributeMapping mapping : CollectionTools.iterable(this.embeddableAttributeMappings())) { + AttributeMapping resolvedMapping = mapping.resolveAttributeMapping(attributeName); + if (resolvedMapping != null) { + return resolvedMapping; + } + } + return null; + } + + + // ********** misc ********** + + public String getKey() { + return MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY; + } + + public int getXmlSequence() { + return 80; + } + + protected JavaEmbeddedMapping2_0 getJavaEmbeddedMapping2_0() { + return (JavaEmbeddedMapping2_0) this.getJavaEmbeddedMapping(); + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmEmbeddedMapping(this); + } + + public void addXmlAttributeMappingTo(Attributes xmlAttributes) { + xmlAttributes.getEmbeddeds().add(this.xmlAttributeMapping); + } + + public void removeXmlAttributeMappingFrom(Attributes xmlAttributes) { + xmlAttributes.getEmbeddeds().remove(this.xmlAttributeMapping); + } + + protected JavaAssociationOverride getSpecifiedJavaAssociationOverrideNamed(String attributeName) { + JavaEmbeddedMapping2_0 javaMapping = this.getJavaEmbeddedMapping2_0(); + return (javaMapping == null) ? null : javaMapping.getAssociationOverrideContainer().getSpecifiedOverrideNamed(attributeName); + } + + @Override + public Relationship resolveOverriddenRelationship(String attributeName) { + return this.isJpa2_0Compatible() ? this.resolveOverriddenRelationship_(attributeName) : null; + } + + protected Relationship resolveOverriddenRelationship_(String attributeName) { + attributeName = this.unqualify(attributeName); + if (attributeName == null) { + return null; + } + AssociationOverride override = this.associationOverrideContainer.getSpecifiedOverrideNamed(attributeName); + // recurse into the target embeddable if necessary + return (override != null) ? override.getRelationship() : this.resolveOverriddenRelationshipInTargetEmbeddable(attributeName); + } + + protected Relationship resolveOverriddenRelationshipInTargetEmbeddable(String attributeName) { + return (this.targetEmbeddable == null) ? null : this.targetEmbeddable.resolveOverriddenRelationship(attributeName); + } + + + // ********** validation ********** + + @Override + protected void validateOverrides(List<IMessage> messages, IReporter reporter) { + super.validateOverrides(messages, reporter); + this.associationOverrideContainer.validate(messages, reporter); + } + + + // ********** association override container owner ********** + + protected class AssociationOverrideContainerOwner + implements OrmAssociationOverrideContainer.Owner + { + protected String getMappingName() { + return GenericOrmEmbeddedMapping.this.getName(); + } + + public OrmTypeMapping getTypeMapping() { + return GenericOrmEmbeddedMapping.this.getTypeMapping(); + } + + public TypeMapping getOverridableTypeMapping() { + return GenericOrmEmbeddedMapping.this.getTargetEmbeddable(); + } + + public Iterator<String> allOverridableNames() { + TypeMapping typeMapping = this.getOverridableTypeMapping(); + return (typeMapping != null) ? typeMapping.allOverridableAssociationNames() : EmptyIterator.<String>instance(); + } + + public EList<XmlAssociationOverride> getXmlOverrides() { + return GenericOrmEmbeddedMapping.this.getXmlAttributeMapping().getAssociationOverrides(); + } + + public Relationship resolveOverriddenRelationship(String attributeName) { + return MappingTools.resolveOverriddenRelationship(this.getOverridableTypeMapping(), attributeName); + } + + public boolean tableNameIsInvalid(String tableName) { + return this.getTypeMapping().tableNameIsInvalid(tableName); + } + + public Iterator<String> candidateTableNames() { + return this.getTypeMapping().allAssociatedTableNames(); + } + + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + return this.getTypeMapping().resolveDbTable(tableName); + } + + public String getDefaultTableName() { + return this.getTypeMapping().getPrimaryTableName(); + } + + public TextRange getValidationTextRange() { + return GenericOrmEmbeddedMapping.this.getValidationTextRange(); + } + + public JptValidator buildValidator(Override_ override, OverrideContainer container, OverrideTextRangeResolver textRangeResolver) { + return new AssociationOverrideValidator(this.getPersistentAttribute(), (AssociationOverride) override, (AssociationOverrideContainer) container, textRangeResolver, new EmbeddableOverrideDescriptionProvider()); + } + + public JptValidator buildColumnValidator(Override_ override, BaseColumn column, BaseColumn.Owner owner, BaseColumnTextRangeResolver textRangeResolver) { + return new AssociationOverrideJoinColumnValidator(this.getPersistentAttribute(), (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(this.getPersistentAttribute(), override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider()); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(AssociationOverride override, JoinColumn column, Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return new AssociationOverrideInverseJoinColumnValidator(this.getPersistentAttribute(), override, column, owner, textRangeResolver, new JoinTableTableDescriptionProvider()); + } + + public JptValidator buildTableValidator(AssociationOverride override, Table table, TableTextRangeResolver textRangeResolver) { + return new AssociationOverrideJoinTableValidator(this.getPersistentAttribute(), override, (JoinTable) table, textRangeResolver); + } + + protected OrmPersistentAttribute getPersistentAttribute() { + return GenericOrmEmbeddedMapping.this.getPersistentAttribute(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEntity.java new file mode 100644 index 0000000000..469d04a4e8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEntity.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmEntity; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.orm.NullOrmCacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.Cacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.CacheableHolder2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmCacheable2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEntity; +import org.eclipse.jpt.jpa.core.resource.orm.v2_0.XmlCacheable_2_0; + +public class GenericOrmEntity + extends AbstractOrmEntity<XmlEntity> +{ + // EclipseLink holds its cacheable in its caching + protected final OrmCacheable2_0 cacheable; + + + public GenericOrmEntity(OrmPersistentType parent, XmlEntity xmlEntity) { + super(parent, xmlEntity); + this.cacheable = this.buildCacheable(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.cacheable.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.cacheable.update(); + } + + + // ********** cacheable ********** + + public OrmCacheable2_0 getCacheable() { + return this.cacheable; + } + + protected OrmCacheable2_0 buildCacheable() { + return this.isJpa2_0Compatible() ? + this.getContextNodeFactory2_0().buildOrmCacheable(this) : + new NullOrmCacheable2_0(this); + } + + public boolean calculateDefaultCacheable() { + CacheableHolder2_0 javaEntity = (CacheableHolder2_0) this.getJavaTypeMappingForDefaults(); + if (javaEntity != null) { + return javaEntity.getCacheable().isCacheable(); + } + + Cacheable2_0 parentCacheable = this.getParentCacheable(); + return (parentCacheable != null) ? + parentCacheable.isCacheable() : + ((PersistenceUnit2_0) this.getPersistenceUnit()).calculateDefaultCacheable(); + } + + protected Cacheable2_0 getParentCacheable() { + CacheableHolder2_0 parentEntity = (CacheableHolder2_0) this.getParentEntity(); + return (parentEntity == null) ? null : parentEntity.getCacheable(); + } + + public XmlCacheable_2_0 getXmlCacheable() { + return this.getXmlTypeMapping(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java new file mode 100644 index 0000000000..d923aec695 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmEnumeratedConverter.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.EnumType; +import org.eclipse.jpt.jpa.core.context.EnumeratedConverter; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmEnumeratedConverter; +import org.eclipse.text.edits.ReplaceEdit; + +public class GenericOrmEnumeratedConverter + extends AbstractOrmConverter + implements OrmEnumeratedConverter +{ + protected EnumType specifiedEnumType; + protected EnumType defaultEnumType; + + + public GenericOrmEnumeratedConverter(OrmAttributeMapping parent) { + super(parent); + this.specifiedEnumType = this.buildSpecifiedEnumType(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedEnumType_(this.buildSpecifiedEnumType()); + } + + @Override + public void update() { + super.update(); + this.setDefaultEnumType(this.buildDefaultEnumType()); + } + + + // ********** enum type ********** + + public EnumType getEnumType() { + return (this.specifiedEnumType != null) ? this.specifiedEnumType : this.getDefaultEnumType(); + } + + public EnumType getSpecifiedEnumType() { + return this.specifiedEnumType; + } + + public void setSpecifiedEnumType(EnumType enumType) { + this.setSpecifiedEnumType_(enumType); + this.setXmlEnumerated(enumType); + } + + protected void setSpecifiedEnumType_(EnumType enumType) { + EnumType old = this.specifiedEnumType; + this.specifiedEnumType = enumType; + this.firePropertyChanged(SPECIFIED_ENUM_TYPE_PROPERTY, old, enumType); + } + + protected void setXmlEnumerated(EnumType enumType) { + this.getXmlConvertibleMapping().setEnumerated(EnumType.toOrmResourceModel(enumType)); + } + + protected EnumType buildSpecifiedEnumType() { + return EnumType.fromOrmResourceModel(this.getXmlConvertibleMapping().getEnumerated()); + } + + public EnumType getDefaultEnumType() { + return this.defaultEnumType; + } + + protected void setDefaultEnumType(EnumType enumType) { + EnumType old = this.defaultEnumType; + this.defaultEnumType = enumType; + this.firePropertyChanged(DEFAULT_ENUM_TYPE_PROPERTY, old, enumType); + } + + /** + * There is no default enum type in XML. + * If you specify the enumerated element, you must + * specify either {@link EnumType#ORDINAL} or + * {@link EnumType#STRING}. + */ + protected EnumType buildDefaultEnumType() { + return null; + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return EnumeratedConverter.class; + } + + public void initialize() { + this.specifiedEnumType = DEFAULT_ENUM_TYPE; + this.setXmlEnumerated(this.specifiedEnumType); + } + + + // ********** refactoring ********** + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return EmptyIterable.instance(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.getXmlConvertibleMapping().getEnumeratedTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java new file mode 100644 index 0000000000..107502d1fe --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratedValue.java @@ -0,0 +1,194 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.GenerationType; +import org.eclipse.jpt.jpa.core.context.Generator; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmGeneratedValue; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +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.orm.XmlGeneratedValue; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> generated value + */ +public class GenericOrmGeneratedValue + extends AbstractOrmXmlContextNode + implements OrmGeneratedValue +{ + protected final XmlGeneratedValue xmlGeneratedValue; + + protected GenerationType specifiedStrategy; + protected GenerationType defaultStrategy; + + protected String specifiedGenerator; + protected String defaultGenerator; + + + public GenericOrmGeneratedValue(XmlContextNode parent, XmlGeneratedValue xmlGeneratedValue) { + super(parent); + this.xmlGeneratedValue = xmlGeneratedValue; + this.specifiedStrategy = this.buildSpecifiedStrategy(); + this.specifiedGenerator = xmlGeneratedValue.getGenerator(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedStrategy_(this.buildSpecifiedStrategy()); + this.setSpecifiedGenerator_(this.xmlGeneratedValue.getGenerator()); + } + + @Override + public void update() { + super.update(); + this.setDefaultStrategy(this.buildDefaultStrategy()); + this.setDefaultGenerator(this.buildDefaultGenerator()); + } + + + // ********** strategy ********** + + public GenerationType getStrategy() { + return (this.specifiedStrategy != null) ? this.specifiedStrategy : this.defaultStrategy; + } + + public GenerationType getSpecifiedStrategy() { + return this.specifiedStrategy; + } + + public void setSpecifiedStrategy(GenerationType strategy) { + this.setSpecifiedStrategy_(strategy); + this.xmlGeneratedValue.setStrategy(GenerationType.toOrmResourceModel(strategy)); + } + + protected void setSpecifiedStrategy_(GenerationType strategy) { + GenerationType old = this.specifiedStrategy; + this.specifiedStrategy = strategy; + this.firePropertyChanged(SPECIFIED_STRATEGY_PROPERTY, old, strategy); + } + + protected GenerationType buildSpecifiedStrategy() { + return GenerationType.fromOrmResourceModel(this.xmlGeneratedValue.getStrategy()); + } + + public GenerationType getDefaultStrategy() { + return this.defaultStrategy; + } + + protected void setDefaultStrategy(GenerationType strategy) { + GenerationType old = this.defaultStrategy; + this.defaultStrategy = strategy; + this.firePropertyChanged(DEFAULT_STRATEGY_PROPERTY, old, strategy); + } + + // TODO + protected GenerationType buildDefaultStrategy() { + return DEFAULT_STRATEGY; + } + + + // ********** generator ********** + + public String getGenerator() { + return (this.specifiedGenerator != null) ? this.specifiedGenerator : this.defaultGenerator; + } + + public String getSpecifiedGenerator() { + return this.specifiedGenerator; + } + + public void setSpecifiedGenerator(String generator) { + this.setSpecifiedGenerator_(generator); + this.xmlGeneratedValue.setGenerator(generator); + } + + protected void setSpecifiedGenerator_(String generator) { + String old = this.specifiedGenerator; + this.specifiedGenerator = generator; + this.firePropertyChanged(SPECIFIED_GENERATOR_PROPERTY, old, generator); + } + + public String getDefaultGenerator() { + return this.defaultGenerator; + } + + protected void setDefaultGenerator(String generator) { + String old = this.defaultGenerator; + this.defaultGenerator = generator; + this.firePropertyChanged(DEFAULT_GENERATOR_PROPERTY, old, generator); + } + + // TODO + protected String buildDefaultGenerator() { + return null; + } + + public TextRange getGeneratorTextRange() { + TextRange textRange = this.xmlGeneratedValue.getGeneratorTextRange(); + return textRange != null ? textRange : this.getValidationTextRange(); + } + + + // ********** misc ********** + + @Override + public XmlContextNode getParent() { + return (XmlContextNode) super.getParent(); + } + + public XmlGeneratedValue getXmlGeneratedValue() { + return this.xmlGeneratedValue; + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + String generator = this.getGenerator(); + if (generator == null) { + return; + } + + for (Iterator<Generator> stream = this.getPersistenceUnit().generators(); stream.hasNext(); ) { + if (generator.equals(stream.next().getName())) { + return; + } + } + + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME, + new String[] {generator}, + this.getParent(), + this.getGeneratorTextRange() + ) + ); + } + + public TextRange getValidationTextRange() { + TextRange validationTextRange = this.xmlGeneratedValue.getValidationTextRange(); + return (validationTextRange != null) ? validationTextRange : this.getParent().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java new file mode 100644 index 0000000000..7cca101c7a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmGeneratorContainer.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.jpa.core.context.Generator; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmGenerator; +import org.eclipse.jpt.jpa.core.context.orm.OrmGeneratorContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmSequenceGenerator; +import org.eclipse.jpt.jpa.core.context.orm.OrmTableGenerator; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +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.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlGeneratorContainer; +import org.eclipse.jpt.jpa.core.resource.orm.XmlSequenceGenerator; +import org.eclipse.jpt.jpa.core.resource.orm.XmlTableGenerator; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmGeneratorContainer + extends AbstractOrmXmlContextNode + implements OrmGeneratorContainer +{ + protected final XmlGeneratorContainer xmlGeneratorContainer; + + protected OrmSequenceGenerator sequenceGenerator; + + protected OrmTableGenerator tableGenerator; + + + public GenericOrmGeneratorContainer(XmlContextNode parent, XmlGeneratorContainer xmlGeneratorContainer) { + super(parent); + this.xmlGeneratorContainer = xmlGeneratorContainer; + this.sequenceGenerator = this.buildSequenceGenerator(); + this.tableGenerator = this.buildTableGenerator(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSequenceGenerator(); + this.syncTableGenerator(); + } + + @Override + public void update() { + super.update(); + if (this.sequenceGenerator != null) { + this.sequenceGenerator.update(); + } + if (this.tableGenerator != null) { + this.tableGenerator.update(); + } + } + + + // ********** sequence generator ********** + + public OrmSequenceGenerator getSequenceGenerator() { + return this.sequenceGenerator; + } + + public OrmSequenceGenerator addSequenceGenerator() { + if (this.sequenceGenerator != null) { + throw new IllegalStateException("sequence generator already exists: " + this.sequenceGenerator); //$NON-NLS-1$ + } + XmlSequenceGenerator xmlGenerator = this.buildXmlSequenceGenerator(); + OrmSequenceGenerator generator = this.buildSequenceGenerator(xmlGenerator); + this.setSequenceGenerator_(generator); + this.xmlGeneratorContainer.setSequenceGenerator(xmlGenerator); + return generator; + } + + protected XmlSequenceGenerator buildXmlSequenceGenerator() { + return OrmFactory.eINSTANCE.createXmlSequenceGenerator(); + } + + public void removeSequenceGenerator() { + if (this.sequenceGenerator == null) { + throw new IllegalStateException("sequence generator does not exist"); //$NON-NLS-1$ + } + this.setSequenceGenerator_(null); + this.xmlGeneratorContainer.setSequenceGenerator(null); + } + + protected OrmSequenceGenerator buildSequenceGenerator() { + XmlSequenceGenerator xmlGenerator = this.getXmlSequenceGenerator(); + return (xmlGenerator == null) ? null : this.buildSequenceGenerator(xmlGenerator); + } + + protected XmlSequenceGenerator getXmlSequenceGenerator() { + return this.xmlGeneratorContainer.getSequenceGenerator(); + } + + protected OrmSequenceGenerator buildSequenceGenerator(XmlSequenceGenerator xmlSequenceGenerator) { + return this.getContextNodeFactory().buildOrmSequenceGenerator(this, xmlSequenceGenerator); + } + + protected void syncSequenceGenerator() { + XmlSequenceGenerator xmlGenerator = this.getXmlSequenceGenerator(); + if (xmlGenerator == null) { + if (this.sequenceGenerator != null) { + this.setSequenceGenerator_(null); + } + } else { + if ((this.sequenceGenerator != null) && (this.sequenceGenerator.getXmlGenerator() == xmlGenerator)) { + this.sequenceGenerator.synchronizeWithResourceModel(); + } else { + this.setSequenceGenerator_(this.buildSequenceGenerator(xmlGenerator)); + } + } + } + + protected void setSequenceGenerator_(OrmSequenceGenerator sequenceGenerator) { + OrmSequenceGenerator old = this.sequenceGenerator; + this.sequenceGenerator = sequenceGenerator; + this.firePropertyChanged(SEQUENCE_GENERATOR_PROPERTY, old, sequenceGenerator); + } + + + // ********** table generator ********** + + public OrmTableGenerator getTableGenerator() { + return this.tableGenerator; + } + + public OrmTableGenerator addTableGenerator() { + if (this.tableGenerator != null) { + throw new IllegalStateException("table generator already exists: " + this.tableGenerator); //$NON-NLS-1$ + } + XmlTableGenerator xmlGenerator = this.buildXmlTableGenerator(); + OrmTableGenerator generator = this.buildTableGenerator(xmlGenerator); + this.setTableGenerator_(generator); + this.xmlGeneratorContainer.setTableGenerator(xmlGenerator); + return generator; + } + + protected XmlTableGenerator buildXmlTableGenerator() { + return OrmFactory.eINSTANCE.createXmlTableGenerator(); + } + + public void removeTableGenerator() { + if (this.tableGenerator == null) { + throw new IllegalStateException("table generator does not exist"); //$NON-NLS-1$ + } + this.setTableGenerator_(null); + this.xmlGeneratorContainer.setTableGenerator(null); + } + + protected OrmTableGenerator buildTableGenerator() { + XmlTableGenerator xmlGenerator = this.getXmlTableGenerator(); + return (xmlGenerator == null) ? null : this.buildTableGenerator(xmlGenerator); + } + + protected XmlTableGenerator getXmlTableGenerator() { + return this.xmlGeneratorContainer.getTableGenerator(); + } + + protected OrmTableGenerator buildTableGenerator(XmlTableGenerator xmlTableGenerator) { + return this.getContextNodeFactory().buildOrmTableGenerator(this, xmlTableGenerator); + } + + protected void syncTableGenerator() { + XmlTableGenerator xmlGenerator = this.getXmlTableGenerator(); + if (xmlGenerator == null) { + if (this.tableGenerator != null) { + this.setTableGenerator_(null); + } + } else { + if ((this.tableGenerator != null) && (this.tableGenerator.getXmlGenerator() == xmlGenerator)) { + this.tableGenerator.synchronizeWithResourceModel(); + } else { + this.setTableGenerator_(this.buildTableGenerator(xmlGenerator)); + } + } + } + + protected void setTableGenerator_(OrmTableGenerator tableGenerator) { + OrmTableGenerator old = this.tableGenerator; + this.tableGenerator = tableGenerator; + this.firePropertyChanged(TABLE_GENERATOR_PROPERTY, old, tableGenerator); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateGenerators(messages); + } + + protected void validateGenerators(List<IMessage> messages) { + for (OrmGenerator localGenerator : this.getGenerators()) { + String name = localGenerator.getName(); + if (StringTools.stringIsEmpty(name)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_NAME_UNDEFINED, + new String[] {}, + localGenerator, + localGenerator.getNameTextRange() + ) + ); + } else { + List<String> reportedNames = new ArrayList<String>(); + for (Iterator<Generator> globalGenerators = this.getPersistenceUnit().generators(); globalGenerators.hasNext(); ) { + if (localGenerator.duplicates(globalGenerators.next()) && !reportedNames.contains(name)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.GENERATOR_DUPLICATE_NAME, + new String[] {name}, + localGenerator, + localGenerator.getNameTextRange() + ) + ); + reportedNames.add(name); + } + } + } + } + } + + protected Iterable<OrmGenerator> getGenerators() { + ArrayList<OrmGenerator> generators = new ArrayList<OrmGenerator>(); + this.addGeneratorsTo(generators); + return generators; + } + + protected void addGeneratorsTo(ArrayList<OrmGenerator> generators) { + if (this.sequenceGenerator != null) { + generators.add(this.sequenceGenerator); + } + if (this.tableGenerator != null) { + generators.add(this.tableGenerator); + } + } + + public TextRange getValidationTextRange() { + return this.xmlGeneratorContainer.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmIdMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmIdMapping.java new file mode 100644 index 0000000000..958b87ddf5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmIdMapping.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmIdMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlId; + +/** + * <code>orm.xml</code> ID mapping + */ +public class GenericOrmIdMapping + extends AbstractOrmIdMapping<XmlId> +{ + public GenericOrmIdMapping(OrmPersistentAttribute parent, XmlId xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java new file mode 100644 index 0000000000..165d659ec5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinColumn.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumn; +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.orm.AbstractOrmBaseColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.orm.XmlJoinColumn; +import org.eclipse.jpt.jpa.db.Column; +import org.eclipse.jpt.jpa.db.Table; + +/** + * <code>orm.xml</code> join column + */ +public class GenericOrmJoinColumn + extends AbstractOrmBaseColumn<XmlJoinColumn, OrmJoinColumn.Owner> + implements OrmJoinColumn +{ + /** @see org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmNamedColumn#AbstractOrmNamedColumn(XmlContextNode, org.eclipse.jpt.jpa.core.context.orm.OrmNamedColumn.Owner, org.eclipse.jpt.jpa.core.resource.orm.AbstractXmlNamedColumn) */ + protected /* final */ XmlJoinColumn xmlColumn; // null for default join columns + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericOrmJoinColumn(XmlContextNode parent, OrmJoinColumn.Owner owner) { + this(parent, owner, null); + } + + public GenericOrmJoinColumn(XmlContextNode parent, OrmJoinColumn.Owner owner, XmlJoinColumn xmlColumn) { + super(parent, owner, xmlColumn); + this.specifiedReferencedColumnName = this.buildSpecifiedReferencedColumnName(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedReferencedColumnName_(this.buildSpecifiedReferencedColumnName()); + } + + @Override + public void update() { + super.update(); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** XML column ********** + + @Override + public XmlJoinColumn getXmlColumn() { + return this.xmlColumn; + } + + @Override + protected void setXmlColumn(XmlJoinColumn xmlColumn) { + this.xmlColumn = xmlColumn; + } + + /** + * join columns are part of a collection; + * the 'join-column' element will be removed/added + * when the XML join column is removed from/added to + * the owner's collection + */ + @Override + protected XmlJoinColumn buildXmlColumn() { + throw new IllegalStateException("XML join column is missing"); //$NON-NLS-1$ + } + + /** + * @see #buildXmlColumn() + */ + @Override + protected void removeXmlColumn() { + // do nothing + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String name) { + this.setSpecifiedReferencedColumnName_(name); + this.getXmlColumn().setReferencedColumnName(name); + } + + protected void setSpecifiedReferencedColumnName_(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + XmlJoinColumn joinColumn = this.getXmlColumn(); + return (joinColumn == null) ? null : joinColumn.getReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.owner); + } + + + // ********** database stuff ********** + + public Table getReferencedColumnDbTable() { + return this.owner.getReferencedColumnDbTable(); + } + + protected Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public boolean referencedColumnIsResolved() { + return this.getReferencedDbColumn() != null; + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyJoinColumn oldColumn) { + super.initializeFrom(oldColumn); + this.setSpecifiedReferencedColumnName(oldColumn.getSpecifiedReferencedColumnName()); + } + + public void initializeFromVirtual(ReadOnlyJoinColumn virtualColumn) { + super.initializeFromVirtual(virtualColumn); + this.setSpecifiedReferencedColumnName(virtualColumn.getReferencedColumnName()); + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.owner); + } + + public TextRange getReferencedColumnNameTextRange() { + return this.getTextRange(this.xmlColumn.getReferencedColumnNameTextRange()); + } + + @Override + protected NamedColumnTextRangeResolver buildTextRangeResolver() { + return new OrmJoinColumnTextRangeResolver(this); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinTable.java new file mode 100644 index 0000000000..a1bfda698f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmJoinTable.java @@ -0,0 +1,511 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.Tools; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +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.LiveCloneIterable; +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.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.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTable; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinTable; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +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.resource.orm.XmlJoinColumn; +import org.eclipse.jpt.jpa.core.resource.orm.XmlJoinTable; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> join table + */ +public class GenericOrmJoinTable + extends GenericOrmReferenceTable<XmlJoinTable> + implements OrmJoinTable +{ + protected final Vector<OrmJoinColumn> specifiedInverseJoinColumns = new Vector<OrmJoinColumn>(); + protected final SpecifiedInverseJoinColumnContainerAdapter specifiedInverseJoinColumnContainerAdapter = new SpecifiedInverseJoinColumnContainerAdapter(); + protected final OrmJoinColumn.Owner inverseJoinColumnOwner; + + protected OrmJoinColumn defaultInverseJoinColumn; + + + public GenericOrmJoinTable(OrmJoinTableRelationshipStrategy parent, Owner owner) { + super(parent, owner); + this.inverseJoinColumnOwner = this.buildInverseJoinColumnOwner(); + this.initializeSpecifiedInverseJoinColumns(); + } + + @Override + protected OrmJoinColumn.Owner buildJoinColumnOwner() { + return new JoinColumnOwner(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedInverseJoinColumns(); + if (this.defaultInverseJoinColumn != null) { + this.defaultInverseJoinColumn.synchronizeWithResourceModel(); + } + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedInverseJoinColumns()); + this.updateDefaultInverseJoinColumn(); + } + + + // ********** XML table ********** + + @Override + protected XmlJoinTable getXmlTable() { + return this.getJoinStrategy().getXmlJoinTable(); + } + + @Override + protected XmlJoinTable buildXmlTable() { + return this.getJoinStrategy().buildXmlJoinTable(); + } + + @Override + protected void removeXmlTable() { + this.getJoinStrategy().removeXmlJoinTable(); + } + + + // ********** inverse join columns ********** + + public ListIterator<OrmJoinColumn> inverseJoinColumns() { + return this.getInverseJoinColumns().iterator(); + } + + protected ListIterable<OrmJoinColumn> getInverseJoinColumns() { + return this.hasSpecifiedInverseJoinColumns() ? this.getSpecifiedInverseJoinColumns() : this.getDefaultInverseJoinColumns(); + } + + public int inverseJoinColumnsSize() { + return this.hasSpecifiedInverseJoinColumns() ? this.specifiedInverseJoinColumnsSize() : this.getDefaultInverseJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedInverseJoinColumn() { + MappingTools.convertJoinTableDefaultToSpecifiedInverseJoinColumn(this); + } + + + // ********** specified inverse join columns ********** + + public ListIterator<OrmJoinColumn> specifiedInverseJoinColumns() { + return this.getSpecifiedInverseJoinColumns().iterator(); + } + + public ListIterable<OrmJoinColumn> getSpecifiedInverseJoinColumns() { + return new LiveCloneListIterable<OrmJoinColumn>(this.specifiedInverseJoinColumns); + } + + public int specifiedInverseJoinColumnsSize() { + return this.specifiedInverseJoinColumns.size(); + } + + public boolean hasSpecifiedInverseJoinColumns() { + return this.specifiedInverseJoinColumns.size() != 0; + } + + public OrmJoinColumn getSpecifiedInverseJoinColumn(int index) { + return this.specifiedInverseJoinColumns.get(index); + } + + public OrmJoinColumn addSpecifiedInverseJoinColumn() { + return this.addSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.size()); + } + + public OrmJoinColumn addSpecifiedInverseJoinColumn(int index) { + XmlJoinTable xmlTable = this.getXmlTableForUpdate(); + XmlJoinColumn xmlJoinColumn = this.buildXmlJoinColumn(); + OrmJoinColumn joinColumn = this.addSpecifiedInverseJoinColumn_(index, xmlJoinColumn); + xmlTable.getInverseJoinColumns().add(index, xmlJoinColumn); + return joinColumn; + } + + public void removeSpecifiedInverseJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedInverseJoinColumn(this.specifiedInverseJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedInverseJoinColumn(int index) { + this.removeSpecifiedInverseJoinColumn_(index); + this.getXmlTable().getInverseJoinColumns().remove(index); + this.removeXmlTableIfUnset(); + } + + protected void removeSpecifiedInverseJoinColumn_(int index) { + this.removeItemFromList(index, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedInverseJoinColumn(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + this.getXmlTable().getInverseJoinColumns().move(targetIndex, sourceIndex); + } + + public void clearSpecifiedInverseJoinColumns() { + this.clearCollection(this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + this.getXmlTable().getInverseJoinColumns().clear(); + } + + protected void initializeSpecifiedInverseJoinColumns() { + for (XmlJoinColumn xmlJoinColumn : this.getXmlInverseJoinColumns()) { + this.specifiedInverseJoinColumns.add(this.buildInverseJoinColumn(xmlJoinColumn)); + } + } + + protected void syncSpecifiedInverseJoinColumns() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedInverseJoinColumnContainerAdapter); + } + + protected Iterable<XmlJoinColumn> getXmlInverseJoinColumns() { + XmlJoinTable xmlTable = this.getXmlTable(); + return (xmlTable == null) ? + EmptyIterable.<XmlJoinColumn>instance() : + // clone to reduce chance of concurrency problems + new LiveCloneIterable<XmlJoinColumn>(xmlTable.getInverseJoinColumns()); + } + + protected void moveSpecifiedInverseJoinColumn_(int index, OrmJoinColumn joinColumn) { + this.moveItemInList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + } + + protected OrmJoinColumn addSpecifiedInverseJoinColumn_(int index, XmlJoinColumn xmlJoinColumn) { + OrmJoinColumn joinColumn = this.buildInverseJoinColumn(xmlJoinColumn); + this.addItemToList(index, joinColumn, this.specifiedInverseJoinColumns, SPECIFIED_INVERSE_JOIN_COLUMNS_LIST); + return joinColumn; + } + + protected void removeSpecifiedInverseJoinColumn_(OrmJoinColumn joinColumn) { + this.removeSpecifiedInverseJoinColumn_(this.specifiedInverseJoinColumns.indexOf(joinColumn)); + } + + /** + * specified inverse join column container adapter + */ + protected class SpecifiedInverseJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<OrmJoinColumn, XmlJoinColumn> + { + public Iterable<OrmJoinColumn> getContextElements() { + return GenericOrmJoinTable.this.getSpecifiedInverseJoinColumns(); + } + public Iterable<XmlJoinColumn> getResourceElements() { + return GenericOrmJoinTable.this.getXmlInverseJoinColumns(); + } + public XmlJoinColumn getResourceElement(OrmJoinColumn contextElement) { + return contextElement.getXmlColumn(); + } + public void moveContextElement(int index, OrmJoinColumn element) { + GenericOrmJoinTable.this.moveSpecifiedInverseJoinColumn_(index, element); + } + public void addContextElement(int index, XmlJoinColumn resourceElement) { + GenericOrmJoinTable.this.addSpecifiedInverseJoinColumn_(index, resourceElement); + } + public void removeContextElement(OrmJoinColumn element) { + GenericOrmJoinTable.this.removeSpecifiedInverseJoinColumn_(element); + } + } + + protected OrmJoinColumn.Owner buildInverseJoinColumnOwner() { + return new InverseJoinColumnOwner(); + } + + + // ********** default inverse join column ********** + + public OrmJoinColumn getDefaultInverseJoinColumn() { + return this.defaultInverseJoinColumn; + } + + protected void setDefaultInverseJoinColumn(OrmJoinColumn joinColumn) { + OrmJoinColumn old = this.defaultInverseJoinColumn; + this.defaultInverseJoinColumn = joinColumn; + this.firePropertyChanged(DEFAULT_INVERSE_JOIN_COLUMN, old, joinColumn); + } + + protected ListIterable<OrmJoinColumn> getDefaultInverseJoinColumns() { + return (this.defaultInverseJoinColumn != null) ? + new SingleElementListIterable<OrmJoinColumn>(this.defaultInverseJoinColumn) : + EmptyListIterable.<OrmJoinColumn>instance(); + } + + protected int getDefaultInverseJoinColumnsSize() { + return (this.defaultInverseJoinColumn == null) ? 0 : 1; + } + + protected void updateDefaultInverseJoinColumn() { + if (this.buildsDefaultInverseJoinColumn()) { + if (this.defaultInverseJoinColumn == null) { + this.setDefaultInverseJoinColumn(this.buildInverseJoinColumn(null)); + } else { + this.defaultInverseJoinColumn.update(); + } + } else { + this.setDefaultInverseJoinColumn(null); + } + } + + protected boolean buildsDefaultInverseJoinColumn() { + return ! this.hasSpecifiedInverseJoinColumns(); + } + + + // ********** misc ********** + + @Override + public OrmJoinTableRelationshipStrategy getParent() { + return (OrmJoinTableRelationshipStrategy) super.getParent(); + } + + protected OrmJoinTableRelationshipStrategy getJoinStrategy() { + return this.getParent(); + } + + @Override + protected String buildDefaultName() { + return this.getJoinStrategy().getJoinTableDefaultName(); + } + + public void initializeFrom(ReadOnlyJoinTable oldTable) { + super.initializeFrom(oldTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(oldTable.specifiedInverseJoinColumns())) { + this.addSpecifiedInverseJoinColumn().initializeFrom(joinColumn); + } + } + + public void initializeFromVirtual(ReadOnlyJoinTable virtualTable) { + super.initializeFromVirtual(virtualTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(virtualTable.inverseJoinColumns())) { + this.addSpecifiedInverseJoinColumn().initializeFromVirtual(joinColumn); + } + } + + protected OrmJoinColumn buildInverseJoinColumn(XmlJoinColumn xmlJoinColumn) { + return this.getContextNodeFactory().buildOrmJoinColumn(this, this.inverseJoinColumnOwner, xmlJoinColumn); + } + + public RelationshipMapping getRelationshipMapping() { + return this.getJoinStrategy().getRelationship().getMapping(); + } + + public PersistentAttribute getPersistentAttribute() { + return this.getRelationshipMapping().getPersistentAttribute(); + } + + + // ********** validation ********** + + @Override + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter) { + super.validateJoinColumns(messages, reporter); + this.validateJoinColumns(this.getInverseJoinColumns(), messages, reporter); + } + + public boolean validatesAgainstDatabase() { + return this.getJoinStrategy().validatesAgainstDatabase(); + } + + + // ********** join column owners ********** + + /** + * just a little common behavior + */ + protected abstract class AbstractJoinColumnOwner + implements OrmJoinColumn.Owner + { + protected AbstractJoinColumnOwner() { + super(); + } + + public TypeMapping getTypeMapping() { + return GenericOrmJoinTable.this.getJoinStrategy().getRelationship().getTypeMapping(); + } + + protected PersistentAttribute getPersistentAttribute() { + return GenericOrmJoinTable.this.getPersistentAttribute(); + } + + /** + * @see MappingTools#buildJoinColumnDefaultName(org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn, org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn.Owner) + */ + public String getDefaultColumnName() { + throw new UnsupportedOperationException(); + } + + /** + * If there is a specified table name it needs to be the same + * the default table name. the table is always the join table + */ + public boolean tableNameIsInvalid(String tableName) { + return Tools.valuesAreDifferent(this.getDefaultTableName(), tableName); + } + + /** + * the join column can only be on the join table itself + */ + public Iterator<String> candidateTableNames() { + return EmptyIterator.instance(); + } + + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + return Tools.valuesAreEqual(GenericOrmJoinTable.this.getName(), tableName) ? + GenericOrmJoinTable.this.getDbTable() : + null; + } + + /** + * by default, the join column is, obviously, in the join table; + * not sure whether it can be anywhere else... + */ + public String getDefaultTableName() { + return GenericOrmJoinTable.this.getName(); + } + + public TextRange getValidationTextRange() { + return GenericOrmJoinTable.this.getValidationTextRange(); + } + + protected boolean isPersistentAttributeVirtual() { + return this.getPersistentAttribute().isVirtual(); + } + + protected String getPersistentAttributeName() { + return this.getPersistentAttribute().getName(); + } + + protected OrmJoinTableRelationshipStrategy getJoinStrategy() { + return GenericOrmJoinTable.this.getJoinStrategy(); + } + } + + + /** + * 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.getJoinStrategy().getRelationship().getEntity(); + } + + public String getAttributeName() { + return MappingTools.getTargetAttributeName(GenericOrmJoinTable.this.getRelationshipMapping()); + } + + @Override + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + org.eclipse.jpt.jpa.db.Table dbTable = super.resolveDbTable(tableName); + return (dbTable != null) ? dbTable : this.getTypeMapping().resolveDbTable(tableName); + } + + public org.eclipse.jpt.jpa.db.Table getReferencedColumnDbTable() { + return this.getTypeMapping().getPrimaryDbTable(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericOrmJoinTable.this.defaultJoinColumn == joinColumn; + } + + public int joinColumnsSize() { + return GenericOrmJoinTable.this.joinColumnsSize(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return this.getJoinStrategy().buildJoinTableJoinColumnValidator((JoinColumn) column, this, (JoinColumnTextRangeResolver) textRangeResolver); + } + } + + + /** + * 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 = GenericOrmJoinTable.this.getRelationshipMapping(); + return (relationshipMapping == null) ? null : relationshipMapping.getResolvedTargetEntity(); + } + + public String getAttributeName() { + RelationshipMapping relationshipMapping = GenericOrmJoinTable.this.getRelationshipMapping(); + return (relationshipMapping == null) ? null : relationshipMapping.getName(); + } + + @Override + public org.eclipse.jpt.jpa.db.Table resolveDbTable(String tableName) { + org.eclipse.jpt.jpa.db.Table dbTable = super.resolveDbTable(tableName); + if (dbTable != null) { + return dbTable; + } + Entity relationshipTarget = this.getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.resolveDbTable(tableName); + } + + public org.eclipse.jpt.jpa.db.Table getReferencedColumnDbTable() { + Entity relationshipTarget = this.getRelationshipTarget(); + return (relationshipTarget == null) ? null : relationshipTarget.getPrimaryDbTable(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericOrmJoinTable.this.defaultInverseJoinColumn == joinColumn; + } + + public int joinColumnsSize() { + return GenericOrmJoinTable.this.inverseJoinColumnsSize(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return this.getJoinStrategy().buildJoinTableInverseJoinColumnValidator((JoinColumn) column, this, (JoinColumnTextRangeResolver) textRangeResolver); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmLobConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmLobConverter.java new file mode 100644 index 0000000000..324ceb7bff --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmLobConverter.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.LobConverter; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmLobConverter; +import org.eclipse.text.edits.ReplaceEdit; + +public class GenericOrmLobConverter + extends AbstractOrmConverter + implements OrmLobConverter +{ + public GenericOrmLobConverter(OrmAttributeMapping parent) { + super(parent); + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return LobConverter.class; + } + + public void initialize() { + this.getXmlConvertibleMapping().setLob(true); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.getXmlConvertibleMapping().getLobTextRange(); + } + + + // ********** refactoring ********** + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return EmptyIterable.instance(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java new file mode 100644 index 0000000000..6a002b3d2e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToManyMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmManyToManyMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlManyToMany; + +public class GenericOrmManyToManyMapping + extends AbstractOrmManyToManyMapping<XmlManyToMany> +{ + public GenericOrmManyToManyMapping(OrmPersistentAttribute parent, XmlManyToMany xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java new file mode 100644 index 0000000000..740c4e01e3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmManyToOneMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmManyToOneMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlManyToOne; + +public class GenericOrmManyToOneMapping + extends AbstractOrmManyToOneMapping<XmlManyToOne> +{ + public GenericOrmManyToOneMapping(OrmPersistentAttribute parent, XmlManyToOne xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java new file mode 100644 index 0000000000..45014549d5 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmMappedSuperclass.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmMappedSuperclass; +import org.eclipse.jpt.jpa.core.resource.orm.XmlMappedSuperclass; + +/** + * <code>orm.xml</code> mapped superclass + */ +public class GenericOrmMappedSuperclass + extends AbstractOrmMappedSuperclass<XmlMappedSuperclass> +{ + public GenericOrmMappedSuperclass(OrmPersistentType parent, XmlMappedSuperclass resourceMapping) { + super(parent, resourceMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java new file mode 100644 index 0000000000..ffc4ce61b8 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedNativeQuery.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmNamedNativeQuery; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmQuery; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedNativeQuery; + +/** + * <code>orm.xml</code> named native query + */ +public class GenericOrmNamedNativeQuery + extends AbstractOrmQuery<XmlNamedNativeQuery> + implements OrmNamedNativeQuery +{ + protected String resultClass; + + protected String resultSetMapping; + + + public GenericOrmNamedNativeQuery(XmlContextNode parent, XmlNamedNativeQuery xmlNamedNativeQuery) { + super(parent, xmlNamedNativeQuery); + this.resultClass = xmlNamedNativeQuery.getResultClass(); + this.resultSetMapping = xmlNamedNativeQuery.getResultSetMapping(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setResultClass_(this.xmlQuery.getResultClass()); + this.setResultSetMapping_(this.xmlQuery.getResultSetMapping()); + } + + + // ********** result class ********** + + public String getResultClass() { + return this.resultClass; + } + + public void setResultClass(String resultClass) { + this.setResultClass_(resultClass); + this.xmlQuery.setResultClass(resultClass); + } + + protected void setResultClass_(String resultClass) { + String old = this.resultClass; + this.resultClass = resultClass; + this.firePropertyChanged(RESULT_CLASS_PROPERTY, old, resultClass); + } + + public char getResultClassEnclosingTypeSeparator() { + return '$'; + } + + + // ********** result set mapping ********** + + public String getResultSetMapping() { + return this.resultSetMapping; + } + + public void setResultSetMapping(String resultSetMapping) { + this.setResultSetMapping_(resultSetMapping); + this.xmlQuery.setResultSetMapping(resultSetMapping); + } + + protected void setResultSetMapping_(String resultSetMapping) { + String old = this.resultSetMapping; + this.resultSetMapping = resultSetMapping; + this.firePropertyChanged(RESULT_SET_MAPPING_PROPERTY, old, resultSetMapping); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java new file mode 100644 index 0000000000..35ef25259f --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmNamedQuery; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmQuery; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedQuery; + +/** + * <code>orm.xml</code> named query + */ +public class GenericOrmNamedQuery + extends AbstractOrmQuery<XmlNamedQuery> + implements OrmNamedQuery +{ + public GenericOrmNamedQuery(XmlContextNode parent, XmlNamedQuery resourceNamedQuery) { + super(parent, resourceNamedQuery); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java new file mode 100644 index 0000000000..374f84e338 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNullAttributeMapping.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNullAttributeMapping; + +/** + * <code>orm.xml</code> null attribute mapping + */ +public class GenericOrmNullAttributeMapping + extends AbstractOrmAttributeMapping<XmlNullAttributeMapping> +{ + public GenericOrmNullAttributeMapping(OrmPersistentAttribute parent, XmlNullAttributeMapping xmlMapping) { + super(parent, xmlMapping); + } + + public String getKey() { + return null; + } + + public int getXmlSequence() { + return -1; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmAttributeMapping(this); + } + + public void addXmlAttributeMappingTo(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + public void removeXmlAttributeMappingFrom(Attributes resourceAttributes) { + throw new UnsupportedOperationException(); + } + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java new file mode 100644 index 0000000000..4fdad7ce7b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToManyMapping.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmOneToManyMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOneToMany; + +public class GenericOrmOneToManyMapping + extends AbstractOrmOneToManyMapping<XmlOneToMany> +{ + public GenericOrmOneToManyMapping(OrmPersistentAttribute parent, XmlOneToMany xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java new file mode 100644 index 0000000000..e89cef7e89 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOneToOneMapping.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmOneToOneMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOneToOne; + +/** + * <code>orm.xml</code> 1:1 mapping + */ +public class GenericOrmOneToOneMapping + extends AbstractOrmOneToOneMapping<XmlOneToOne> +{ + public GenericOrmOneToOneMapping(OrmPersistentAttribute parent, XmlOneToOne xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOrderable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOrderable.java new file mode 100644 index 0000000000..a86fd056d3 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOrderable.java @@ -0,0 +1,452 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +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.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.OrderColumnValidator; +import org.eclipse.jpt.jpa.core.jpa2.context.OrderColumn2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmOrderColumn2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmOrderable2_0; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOrderColumn; +import org.eclipse.jpt.jpa.core.resource.orm.XmlOrderable; +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> ordering + * <p> + * <strong>NB:</strong> Setting any flag to <code>false</code> (or setting the + * specified "order by" to <code>null</code>) can be a bit unpredictable. The + * intent is to set a flag to <code>true</code> (or set the specified "order by" + * to a non-<code>null</code> value). + * <p> + * <strong>(JPA 2.0 only) NB:</strong> If both the "order-by" and the + * "order-column" elements are present (which is prohibited by the JPA spec), + * both are ignored. + */ +public class GenericOrmOrderable + extends AbstractOrmXmlContextNode + implements OrmOrderable2_0 +{ + protected String specifiedOrderBy; + protected boolean noOrdering = false; + protected boolean pkOrdering = false; + protected boolean customOrdering = false; + + // JPA 2.0 + protected final Owner owner; // this is null for JPA 1.0 mappings + protected boolean orderColumnOrdering = false; + protected final OrmOrderColumn2_0 orderColumn; // this is null for JPA 1.0 mappings + + + /** + * JPA 1.0 + */ + public GenericOrmOrderable(OrmAttributeMapping parent) { + this(parent, null); + } + + /** + * JPA 2.0 + */ + public GenericOrmOrderable(OrmAttributeMapping parent, Owner owner) { + super(parent); + + this.specifiedOrderBy = this.buildSpecifiedOrderBy(); + this.noOrdering = this.buildNoOrdering(); + this.pkOrdering = this.buildPkOrdering(); + this.customOrdering = this.buildCustomOrdering(); + + this.owner = owner; + this.orderColumnOrdering = this.buildOrderColumnOrdering(); + this.orderColumn = this.buildOrderColumn(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + + this.setSpecifiedOrderBy_(this.buildSpecifiedOrderBy()); + this.setNoOrdering_(this.buildNoOrdering()); + this.setPkOrdering_(this.buildPkOrdering()); + this.setCustomOrdering_(this.buildCustomOrdering()); + + this.setOrderColumnOrdering_(this.buildOrderColumnOrdering()); + if (this.orderColumn != null) { + this.orderColumn.synchronizeWithResourceModel(); + } + } + + @Override + public void update() { + super.update(); + if (this.orderColumn != null) { + this.orderColumn.update(); + } + } + + + // ********** specified order by ********** + + public String getSpecifiedOrderBy() { + return this.specifiedOrderBy; + } + + public void setSpecifiedOrderBy(String orderBy) { + if (orderBy != null) { + this.setSpecifiedOrderBy_(orderBy); + this.setNoOrdering_(false); + this.setPkOrdering_(orderBy.length() == 0); + this.setCustomOrdering_(orderBy.length() != 0); + this.setOrderColumnOrdering_(false); + + this.removeXmlOrderColumn(); + this.getXmlOrderable().setOrderBy(orderBy); + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setSpecifiedOrderBy_(String orderBy) { + String old = this.specifiedOrderBy; + this.specifiedOrderBy = orderBy; + this.firePropertyChanged(SPECIFIED_ORDER_BY_PROPERTY, old, orderBy); + } + + protected String buildSpecifiedOrderBy() { + if (this.xmlOrderColumnIsPresent()) { + return null; + } + return this.getXmlOrderBy(); + } + + + // ********** no ordering ********** + + public boolean isNoOrdering() { + return this.noOrdering; + } + + public void setNoOrdering(boolean noOrdering) { + if (noOrdering) { + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(true); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(false); + + this.removeXmlOrderColumn(); + this.getXmlOrderable().setOrderBy(null); + } else { + this.setPkOrdering(true); // hmmm... + } + } + + protected void setNoOrdering_(boolean noOrdering) { + boolean old = this.noOrdering; + this.noOrdering = noOrdering; + this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); + } + + protected boolean buildNoOrdering() { + return this.isJpa2_0Compatible() ? this.buildNoOrdering2_0() : this.buildNoOrdering1_0(); + } + + /** + * both elements are missing <em>or</em> both are present + */ + protected boolean buildNoOrdering2_0() { + boolean orderByMissing = (this.getXmlOrderBy() == null); + boolean orderByPresent = ! orderByMissing; + boolean orderColumnMissing = (this.getXmlOrderColumn() == null); + boolean orderColumnPresent = ! orderColumnMissing; + return (orderByMissing && orderColumnMissing) || (orderByPresent && orderColumnPresent); + } + + /** + * the order-by element is missing + */ + protected boolean buildNoOrdering1_0() { + return this.getXmlOrderBy() == null; + } + + + // ********** pk ordering ********** + + public boolean isPkOrdering() { + return this.pkOrdering; + } + + public void setPkOrdering(boolean pkOrdering) { + if (pkOrdering) { + this.setSpecifiedOrderBy(""); //$NON-NLS-1$ + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setPkOrdering_(boolean pkOrdering) { + boolean old = this.pkOrdering; + this.pkOrdering = pkOrdering; + this.firePropertyChanged(PK_ORDERING_PROPERTY, old, pkOrdering); + } + + /** + * the order-by element is present but no value specified + */ + protected boolean buildPkOrdering() { + if (this.xmlOrderColumnIsPresent()) { + return false; + } + String xmlOrderBy = this.getXmlOrderBy(); + return (xmlOrderBy != null) && (xmlOrderBy.length() == 0); + } + + + // ********** custom ordering ********** + + public boolean isCustomOrdering() { + return this.customOrdering; + } + + /** + * Unfortunately, setting the "custom ordering" flag directly is a bit hacky: + * The "specified order-by" is initially set to an empty string, which is + * the same as a "primary key ordering" state.... + */ + public void setCustomOrdering(boolean customOrdering) { + if (customOrdering) { + this.setSpecifiedOrderBy_(""); // hmmm... //$NON-NLS-1$ + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(true); + this.setOrderColumnOrdering_(false); + + this.removeXmlOrderColumn(); + this.getXmlOrderable().setOrderBy(""); //$NON-NLS-1$ + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setCustomOrdering_(boolean customOrdering) { + boolean old = this.customOrdering; + this.customOrdering = customOrdering; + this.firePropertyChanged(CUSTOM_ORDERING_PROPERTY, old, customOrdering); + } + + /** + * the order-by element is present and it has a specified value + */ + protected boolean buildCustomOrdering() { + if (this.xmlOrderColumnIsPresent()) { + return false; + } + String xmlOrderBy = this.getXmlOrderBy(); + return (xmlOrderBy != null) && (xmlOrderBy.length() != 0); + } + + + // ********** order column ordering ********** + + public boolean isOrderColumnOrdering() { + return this.orderColumnOrdering; + } + + public void setOrderColumnOrdering(boolean orderColumnOrdering) { + if (orderColumnOrdering) { + this.setSpecifiedOrderBy_(null); + this.setNoOrdering_(false); + this.setPkOrdering_(false); + this.setCustomOrdering_(false); + this.setOrderColumnOrdering_(true); + + this.getXmlOrderable().setOrderBy(null); + this.buildXmlOrderColumn(); + } else { + this.setNoOrdering(true); // hmmm... + } + } + + protected void setOrderColumnOrdering_(boolean orderColumnOrdering) { + boolean old = this.orderColumnOrdering; + this.orderColumnOrdering = orderColumnOrdering; + this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); + } + + /** + * JPA 2.0 only; + * the <code>order-column</code> element is present <em>and</em> + * the <code>order-by</code> element is missing + */ + protected boolean buildOrderColumnOrdering() { + return this.xmlOrderColumnIsPresent() && + (this.getXmlOrderBy() == null); + } + + + // ********** order column ********** + + public OrmOrderColumn2_0 getOrderColumn() { + return this.orderColumn; + } + + /** + * JPA 2.0 only + */ + protected OrmOrderColumn2_0 buildOrderColumn() { + return this.isJpa2_0Compatible() ? this.buildOrderColumn_() : null; + } + + protected OrmOrderColumn2_0 buildOrderColumn_() { + return this.getContextNodeFactory2_0().buildOrmOrderColumn(this, new OrderColumnOwner()); + } + + + // ********** xml order by ********** + + protected String getXmlOrderBy() { + return this.getXmlOrderable().getOrderBy(); + } + + + // ********** xml order column ********** + + protected XmlOrderColumn getXmlOrderColumn() { + return this.getXmlOrderable().getOrderColumn(); + } + + /** + * NB: Only return <code>true</code> for JPA 2.0 mappings. + */ + protected boolean xmlOrderColumnIsPresent() { + return this.isJpa2_0Compatible() && (this.getXmlOrderColumn() != null); + } + + protected XmlOrderColumn buildXmlOrderColumn() { + XmlOrderColumn xmlColumn = OrmFactory.eINSTANCE.createXmlOrderColumn(); + GenericOrmOrderable.this.getXmlOrderable().setOrderColumn(xmlColumn); + return xmlColumn; + } + + protected void removeXmlOrderColumn() { + if (this.xmlOrderColumnIsPresent()) { + this.getXmlOrderable().setOrderColumn(null); + } + } + + + // ********** misc ********** + + @Override + public OrmAttributeMapping getParent() { + return (OrmAttributeMapping) super.getParent(); + } + + protected OrmAttributeMapping getAttributeMapping() { + return this.getParent(); + } + + protected OrmPersistentAttribute getPersistentAttribute() { + return this.getAttributeMapping().getPersistentAttribute(); + } + + protected XmlOrderable getXmlOrderable() { + return (XmlOrderable) this.getAttributeMapping().getXmlAttributeMapping(); + } + + // JPA 2.0 + public String getDefaultTableName() { + return this.owner.getTableName(); + } + + // JPA 2.0 + protected Table resolveDbTable(String tableName) { + return this.owner.resolveDbTable(tableName); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + TextRange textRange = this.getXmlOrderable().getValidationTextRange(); + return (textRange != null) ? textRange : this.getAttributeMapping().getValidationTextRange(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + // order-column and order-by both specified is handled with schema validation + if (this.orderColumnOrdering) { + // TODO validation message if type is not List + this.orderColumn.validate(messages, reporter); + } + } + + + // ********** order column owner (JPA 2.0) ********** + + protected class OrderColumnOwner + implements OrmOrderColumn2_0.Owner + { + public String getDefaultTableName() { + return GenericOrmOrderable.this.getDefaultTableName(); + } + + public Table resolveDbTable(String tableName) { + return GenericOrmOrderable.this.resolveDbTable(tableName); + } + + public String getDefaultColumnName() { + return this.getPersistentAttribute().getName() + "_ORDER"; //$NON-NLS-1$ + } + + public TypeMapping getTypeMapping() { + return this.getPersistentAttribute().getOwningTypeMapping(); + } + + public TextRange getValidationTextRange() { + return GenericOrmOrderable.this.getValidationTextRange(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return new OrderColumnValidator(this.getPersistentAttribute(), (OrderColumn2_0) column, textRangeResolver); + } + + public XmlOrderColumn getXmlColumn() { + return GenericOrmOrderable.this.getXmlOrderColumn(); + } + + public XmlOrderColumn buildXmlColumn() { + return GenericOrmOrderable.this.buildXmlOrderColumn(); + } + + public void removeXmlColumn() { + GenericOrmOrderable.this.removeXmlOrderColumn(); + } + + protected OrmPersistentAttribute getPersistentAttribute() { + return GenericOrmOrderable.this.getPersistentAttribute(); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOverrideRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOverrideRelationship.java new file mode 100644 index 0000000000..f669f9864d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmOverrideRelationship.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.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.MappedByRelationship; +import org.eclipse.jpt.jpa.core.context.OverrideRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumnRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinTableRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyOverrideRelationship; +import org.eclipse.jpt.jpa.core.context.ReadOnlyRelationship; +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.Table; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.orm.OrmRelationshipStrategy; +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.TableTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.internal.context.orm.GenericOrmOverrideJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.orm.NullOrmJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.orm.GenericOrmOverrideJoinTableRelationshipStrategy2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmOverrideRelationship2_0; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAssociationOverride; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +public class GenericOrmOverrideRelationship + extends AbstractOrmXmlContextNode + implements OrmOverrideRelationship2_0 +{ + protected OrmRelationshipStrategy strategy; + + protected final OrmJoinColumnRelationshipStrategy joinColumnStrategy; + + // JPA 2.0 + protected final OrmJoinTableRelationshipStrategy joinTableStrategy; + + + public GenericOrmOverrideRelationship(OrmAssociationOverride parent) { + super(parent); + this.joinColumnStrategy = this.buildJoinColumnStrategy(); + this.joinTableStrategy = this.buildJoinTableStrategy(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.joinColumnStrategy.synchronizeWithResourceModel(); + this.joinTableStrategy.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.setStrategy(this.buildStrategy()); + this.joinColumnStrategy.update(); + this.joinTableStrategy.update(); + } + + + // ********** strategy ********** + + public OrmRelationshipStrategy getStrategy() { + return this.strategy; + } + + protected void setStrategy(OrmRelationshipStrategy strategy) { + OrmRelationshipStrategy old = this.strategy; + this.strategy = strategy; + this.firePropertyChanged(STRATEGY_PROPERTY, old, strategy); + } + + protected OrmRelationshipStrategy buildStrategy() { + if (this.isJpa2_0Compatible()) { + if (this.joinColumnStrategy.hasSpecifiedJoinColumns()) { + return this.joinColumnStrategy; + } + return this.joinTableStrategy; + } + return this.joinColumnStrategy; + } + + + // ********** join column strategy ********** + + public OrmJoinColumnRelationshipStrategy getJoinColumnStrategy() { + return this.joinColumnStrategy; + } + + public boolean strategyIsJoinColumn() { + return this.strategy == this.joinColumnStrategy; + } + + public void setStrategyToJoinColumn() { + this.joinColumnStrategy.addStrategy(); + this.joinTableStrategy.removeStrategy(); + } + + public boolean mayHaveDefaultJoinColumn() { + return false; + } + + protected OrmJoinColumnRelationshipStrategy buildJoinColumnStrategy() { + return new GenericOrmOverrideJoinColumnRelationshipStrategy(this); + } + + + // ********** join table strategy ********** + + public OrmJoinTableRelationshipStrategy getJoinTableStrategy() { + return this.joinTableStrategy; + } + + public boolean strategyIsJoinTable() { + return this.strategy == this.joinTableStrategy; + } + + public void setStrategyToJoinTable() { + this.joinTableStrategy.addStrategy(); + this.joinColumnStrategy.removeStrategy(); + } + + public boolean mayHaveDefaultJoinTable() { + return false; + } + + protected OrmJoinTableRelationshipStrategy buildJoinTableStrategy() { + return this.isJpa2_0Compatible() ? + new GenericOrmOverrideJoinTableRelationshipStrategy2_0(this) : + new NullOrmJoinTableRelationshipStrategy(this); + } + + + // ********** conversions ********** + + public void initializeFrom(ReadOnlyRelationship oldRelationship) { + oldRelationship.initializeOn(this); + } + + public void initializeOn(Relationship newRelationship) { + newRelationship.initializeFromJoinTableRelationship(this); + newRelationship.initializeFromJoinColumnRelationship(this); + } + + public void initializeFromMappedByRelationship(MappedByRelationship oldRelationship) { + // NOP + } + + public void initializeFromJoinTableRelationship(ReadOnlyJoinTableRelationship oldRelationship) { + this.joinTableStrategy.initializeFrom(oldRelationship.getJoinTableStrategy()); + } + + public void initializeFromJoinColumnRelationship(ReadOnlyJoinColumnRelationship oldRelationship) { + this.joinColumnStrategy.initializeFrom(oldRelationship.getJoinColumnStrategy()); + } + + public void initializeFromVirtual(ReadOnlyOverrideRelationship virtualRelationship) { + virtualRelationship.initializeOnSpecified(this); + } + + public void initializeOnSpecified(OverrideRelationship specifiedRelationship) { + throw new UnsupportedOperationException(); + } + + public void initializeFromVirtualJoinTableRelationship(ReadOnlyJoinTableRelationship virtualRelationship) { + this.joinTableStrategy.initializeFromVirtual(virtualRelationship.getJoinTableStrategy()); + } + + public void initializeFromVirtualJoinColumnRelationship(ReadOnlyJoinColumnRelationship virtualRelationship) { + this.joinColumnStrategy.initializeFromVirtual(virtualRelationship.getJoinColumnStrategy()); + } + + + // ********** misc ********** + + @Override + public OrmAssociationOverride getParent() { + return (OrmAssociationOverride) super.getParent(); + } + + public OrmAssociationOverride getAssociationOverride() { + return this.getParent(); + } + + public XmlAssociationOverride getXmlContainer() { + return this.getAssociationOverride().getXmlOverride(); + } + + public TypeMapping getTypeMapping() { + return this.getAssociationOverride().getContainer().getTypeMapping(); + } + + public Entity getEntity() { + TypeMapping typeMapping = this.getTypeMapping(); + return (typeMapping instanceof Entity) ? (Entity) typeMapping : null; + } + + public boolean isVirtual() { + return false; + } + + public RelationshipMapping getMapping() { + return this.getAssociationOverride().getMapping(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.getAssociationOverride().getValidationTextRange(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.joinColumnStrategy.validate(messages, reporter); + this.joinTableStrategy.validate(messages, reporter); + } + + public JptValidator buildJoinTableJoinColumnValidator(JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return this.getAssociationOverride().getContainer().buildJoinTableJoinColumnValidator(this.getAssociationOverride(), column, owner, textRangeResolver); + } + + public JptValidator buildJoinTableInverseJoinColumnValidator(JoinColumn column, JoinColumn.Owner owner, JoinColumnTextRangeResolver textRangeResolver) { + return this.getAssociationOverride().getContainer().buildJoinTableInverseJoinColumnValidator(this.getAssociationOverride(), column, owner, textRangeResolver); + } + + public JptValidator buildTableValidator(Table table, TableTextRangeResolver textRangeResolver) { + return this.getAssociationOverride().getContainer().buildTableValidator(this.getAssociationOverride(), table, textRangeResolver); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitDefaults.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitDefaults.java new file mode 100644 index 0000000000..7ff900e4d1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitDefaults.java @@ -0,0 +1,344 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.AccessType; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistenceUnitMetadata; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmPersistenceUnitDefaults2_0; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlPersistenceUnitDefaults; +import org.eclipse.jpt.jpa.core.resource.orm.XmlPersistenceUnitMetadata; +import org.eclipse.jpt.jpa.db.Catalog; +import org.eclipse.jpt.jpa.db.Schema; +import org.eclipse.jpt.jpa.db.SchemaContainer; + +/** + * <code>orm.xml</code> file + * <br> + * <code>persistence-unit-defaults</code> element + */ +public class GenericOrmPersistenceUnitDefaults + extends AbstractOrmXmlContextNode + implements OrmPersistenceUnitDefaults2_0 +{ + protected AccessType access; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedSchema; + protected String defaultSchema; + + protected boolean cascadePersist; + + protected boolean delimitedIdentifiers; + + + // ********** constructor/initialization ********** + + public GenericOrmPersistenceUnitDefaults(OrmPersistenceUnitMetadata parent) { + super(parent); + this.access = this.buildAccess(); + this.specifiedCatalog = this.buildSpecifiedCatalog(); + this.specifiedSchema = this.buildSpecifiedSchema(); + this.cascadePersist = this.buildCascadePersist(); + this.delimitedIdentifiers = this.buildDelimitedIdentifiers(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setAccess_(this.buildAccess()); + this.setSpecifiedCatalog_(this.buildSpecifiedCatalog()); + this.setSpecifiedSchema_(this.buildSpecifiedSchema()); + this.setCascadePersist_(this.buildCascadePersist()); + this.setDelimitedIdentifiers_(this.buildDelimitedIdentifiers()); + } + + @Override + public void update() { + super.update(); + this.setDefaultCatalog(this.buildDefaultCatalog()); + this.setDefaultSchema(this.buildDefaultSchema()); + } + + + // ********** access ********** + + public AccessType getAccess() { + return this.access; + } + + public void setAccess(AccessType access) { + if (this.valuesAreDifferent(this.access, access)) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + this.setAccess_(access); + xmlDefaults.setAccess(AccessType.toOrmResourceModel(access)); + this.removeXmlDefaultsIfUnset(); + } + } + + protected void setAccess_(AccessType access) { + AccessType old = this.access; + this.access = access; + this.firePropertyChanged(ACCESS_PROPERTY, old, access); + } + + protected AccessType buildAccess() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults == null) ? null : AccessType.fromOrmResourceModel(xmlDefaults.getAccess()); + } + + + // ********** schema container ********** + + /** + * If we don't have a catalog (i.e. we don't even have a <em>default</em> catalog), + * then the database probably does not support catalogs; and we need to + * get the schema directly from the database. + */ + public SchemaContainer getDbSchemaContainer() { + String catalog = this.getCatalog(); + return (catalog != null) ? this.resolveDbCatalog(catalog) : this.getDatabase(); + } + + + // ********** catalog ********** + + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + if (this.valuesAreDifferent(this.specifiedCatalog, catalog)) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + this.setSpecifiedCatalog_(catalog); + xmlDefaults.setCatalog(catalog); + this.removeXmlDefaultsIfUnset(); + } + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + protected String buildSpecifiedCatalog() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults == null) ? null : xmlDefaults.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 String buildDefaultCatalog() { + return this.getJpaProject().getDefaultCatalog(); + } + + /** + * 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); + } + + + // ********** 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)) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + this.setSpecifiedSchema_(schema); + xmlDefaults.setSchema(schema); + this.removeXmlDefaultsIfUnset(); + } + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + protected String buildSpecifiedSchema() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults == null) ? null : xmlDefaults.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 String buildDefaultSchema() { + return this.getJpaProject().getDefaultSchema(); + } + + public Schema getDbSchema() { + SchemaContainer dbSchemaContainer = this.getDbSchemaContainer(); + return (dbSchemaContainer == null) ? null : dbSchemaContainer.getSchemaForIdentifier(this.getSchema()); + } + + + // ********** cascade persist ********** + + public boolean isCascadePersist() { + return this.cascadePersist; + } + + public void setCascadePersist(boolean cascadePersist) { + if (this.cascadePersist != cascadePersist) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + this.setCascadePersist_(cascadePersist); + xmlDefaults.setCascadePersist(cascadePersist); + this.removeXmlDefaultsIfUnset(); + } + } + + protected void setCascadePersist_(boolean cascadePersist) { + boolean old = this.cascadePersist; + this.cascadePersist = cascadePersist; + this.firePropertyChanged(CASCADE_PERSIST_PROPERTY, old, cascadePersist); + } + + protected boolean buildCascadePersist() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults == null) ? false : xmlDefaults.isCascadePersist(); + } + + + // ********** delimited identifiers ********** + + public boolean isDelimitedIdentifiers() { + return this.delimitedIdentifiers; + } + + public void setDelimitedIdentifiers(boolean delimitedIdentifiers) { + if (this.delimitedIdentifiers != delimitedIdentifiers) { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaultsForUpdate(); + this.setDelimitedIdentifiers_(delimitedIdentifiers); + xmlDefaults.setDelimitedIdentifiers(delimitedIdentifiers); + this.removeXmlDefaultsIfUnset(); + } + } + + protected void setDelimitedIdentifiers_(boolean di) { + boolean old = this.delimitedIdentifiers; + this.delimitedIdentifiers = di; + this.firePropertyChanged(DELIMITED_IDENTIFIERS_PROPERTY, old, di); + } + + protected boolean buildDelimitedIdentifiers() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults == null) ? false : xmlDefaults.isDelimitedIdentifiers(); + } + + + // ********** XML defaults ********** + + /** + * Return <code>null</code> if the XML defaults does not exist. + */ + protected XmlPersistenceUnitDefaults getXmlDefaults() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata == null) ? null : xmlMetadata.getPersistenceUnitDefaults(); + } + + protected XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadata() { + return this.getPersistenceUnitMetadata().getXmlPersistenceUnitMetadata(); + } + + /** + * Build the XML defaults (and XML metadata if necessary) if it does not exist. + */ + protected XmlPersistenceUnitDefaults getXmlDefaultsForUpdate() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadataForUpdate(); + XmlPersistenceUnitDefaults xmlDefaults = xmlMetadata.getPersistenceUnitDefaults(); + return (xmlDefaults != null) ? xmlDefaults : this.buildXmlDefaults(xmlMetadata); + } + + protected XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadataForUpdate() { + return this.getPersistenceUnitMetadata().getXmlPersistenceUnitMetadataForUpdate(); + } + + protected XmlPersistenceUnitDefaults buildXmlDefaults(XmlPersistenceUnitMetadata xmlMetadata) { + XmlPersistenceUnitDefaults xmlDefaults = OrmFactory.eINSTANCE.createXmlPersistenceUnitDefaults(); + xmlMetadata.setPersistenceUnitDefaults(xmlDefaults); + return xmlDefaults; + } + + /** + * clear the XML defaults (and the XML metadata) if appropriate + */ + protected void removeXmlDefaultsIfUnset() { + if (this.getXmlDefaults().isUnset()) { + this.getXmlPersistenceUnitMetadata().setPersistenceUnitDefaults(null); + this.removeXmlPersistenceUnitMetadataIfUnset(); + } + } + + protected void removeXmlPersistenceUnitMetadataIfUnset() { + this.getPersistenceUnitMetadata().removeXmlPersistenceUnitMetadataIfUnset(); + } + + + // ********** misc ********** + + @Override + public OrmPersistenceUnitMetadata getParent() { + return (OrmPersistenceUnitMetadata) super.getParent(); + } + + public OrmPersistenceUnitMetadata getPersistenceUnitMetadata() { + return this.getParent(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + XmlPersistenceUnitDefaults xmlDefaults = this.getXmlDefaults(); + return (xmlDefaults != null) ? + xmlDefaults.getValidationTextRange() : + this.getPersistenceUnitMetadata().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitMetadata.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitMetadata.java new file mode 100644 index 0000000000..63409c28f1 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistenceUnitMetadata.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.orm.EntityMappings; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistenceUnitDefaults; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmPersistenceUnitMetadata2_0; +import org.eclipse.jpt.jpa.core.resource.orm.OrmPackage; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEntityMappings; +import org.eclipse.jpt.jpa.core.resource.orm.XmlPersistenceUnitMetadata; +import org.eclipse.jpt.jpa.core.resource.xml.EmfTools; + +/** + * <code>orm.xml</code> file + * <br> + * <code>persistence-unit-metadata</code> element + */ +public class GenericOrmPersistenceUnitMetadata + extends AbstractOrmXmlContextNode + implements OrmPersistenceUnitMetadata2_0 +{ + protected boolean xmlMappingMetadataComplete; + + protected String description; + + // never null + protected final OrmPersistenceUnitDefaults persistenceUnitDefaults; + + + public GenericOrmPersistenceUnitMetadata(EntityMappings parent) { + super(parent); + this.xmlMappingMetadataComplete = this.buildXmlMappingMetadataComplete(); + this.description = this.buildDescription(); + this.persistenceUnitDefaults = this.buildPersistenceUnitDefaults(); + } + + protected OrmPersistenceUnitDefaults buildPersistenceUnitDefaults() { + return this.getContextNodeFactory().buildOrmPersistenceUnitDefaults(this); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setXmlMappingMetadataComplete_(this.buildXmlMappingMetadataComplete()); + this.setDescription_(this.buildDescription()); + this.persistenceUnitDefaults.synchronizeWithResourceModel(); + } + + @Override + public void update() { + super.update(); + this.persistenceUnitDefaults.update(); + } + + + // ********** XML metadata ********** + + /** + * Return <code>null</code> if the XML metadata does not exist. + */ + public XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadata() { + return this.getXmlEntityMappings().getPersistenceUnitMetadata(); + } + + /** + * Build the XML metadata if it does not exist. + */ + public XmlPersistenceUnitMetadata getXmlPersistenceUnitMetadataForUpdate() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata != null) ? xmlMetadata : this.buildXmlPersistenceUnitMetadata(); + } + + protected XmlPersistenceUnitMetadata buildXmlPersistenceUnitMetadata() { + XmlPersistenceUnitMetadata xmlMetadata = this.buildXmlPersistenceUnitMetadata_(); + this.getXmlEntityMappings().setPersistenceUnitMetadata(xmlMetadata); + return xmlMetadata; + } + + protected XmlPersistenceUnitMetadata buildXmlPersistenceUnitMetadata_() { + return EmfTools.create( + this.getResourceNodeFactory(), + OrmPackage.eINSTANCE.getXmlPersistenceUnitMetadata(), + XmlPersistenceUnitMetadata.class + ); + } + + public void removeXmlPersistenceUnitMetadataIfUnset() { + if (this.getXmlPersistenceUnitMetadata().isUnset()) { + this.getXmlEntityMappings().setPersistenceUnitMetadata(null); + } + } + + + // ********** XML mapping metadata complete ********** + + public boolean isXmlMappingMetadataComplete() { + return this.xmlMappingMetadataComplete; + } + + public void setXmlMappingMetadataComplete(boolean xmlMappingMetadataComplete) { + if (this.xmlMappingMetadataComplete != xmlMappingMetadataComplete) { + XmlPersistenceUnitMetadata xmlPersistenceUnitMetadata = this.getXmlPersistenceUnitMetadataForUpdate(); + this.setXmlMappingMetadataComplete_(xmlMappingMetadataComplete); + xmlPersistenceUnitMetadata.setXmlMappingMetadataComplete(xmlMappingMetadataComplete); + this.removeXmlPersistenceUnitMetadataIfUnset(); + } + } + + protected void setXmlMappingMetadataComplete_(boolean xmlMappingMetadataComplete) { + boolean old = this.xmlMappingMetadataComplete; + this.xmlMappingMetadataComplete = xmlMappingMetadataComplete; + this.firePropertyChanged(XML_MAPPING_METADATA_COMPLETE_PROPERTY, old, xmlMappingMetadataComplete); + } + + protected boolean buildXmlMappingMetadataComplete() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata != null) ? xmlMetadata.isXmlMappingMetadataComplete() : false; + } + + + // ********** description ********** + + public String getDescription() { + return this.description; + } + + public void setDescription(String description) { + if (this.valuesAreDifferent(this.description, description)) { + XmlPersistenceUnitMetadata xmlPersistenceUnitMetadata = this.getXmlPersistenceUnitMetadataForUpdate(); + this.setDescription_(description); + xmlPersistenceUnitMetadata.setDescription(description); + this.removeXmlPersistenceUnitMetadataIfUnset(); + } + } + + protected void setDescription_(String description) { + String old = this.description; + this.description = description; + this.firePropertyChanged(DESCRIPTION_PROPERTY, old, description); + } + + protected String buildDescription() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata == null) ? null : xmlMetadata.getDescription(); + } + + + // ********** persistence unit defaults ********** + + public OrmPersistenceUnitDefaults getPersistenceUnitDefaults() { + return this.persistenceUnitDefaults; + } + + + // ********** misc ********** + + @Override + public EntityMappings getParent() { + return (EntityMappings) super.getParent(); + } + + public XmlEntityMappings getXmlEntityMappings() { + return this.getParent().getXmlEntityMappings(); + } + + public boolean resourceExists() { + return this.getXmlPersistenceUnitMetadata() != null; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + XmlPersistenceUnitMetadata xmlMetadata = this.getXmlPersistenceUnitMetadata(); + return (xmlMetadata != null) ? + xmlMetadata.getValidationTextRange() : + this.getXmlEntityMappings().getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.java new file mode 100644 index 0000000000..1bdd5cc4c0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentAttribute.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.jpa1.context.orm; + +import java.util.List; +import org.eclipse.jpt.jpa.core.context.AccessType; +import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.internal.context.JptValidator; +import org.eclipse.jpt.jpa.core.internal.context.orm.SpecifiedOrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.GenericPersistentAttributeValidator; +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.orm.XmlAttributeMapping; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> persistent attribute + */ +public class GenericOrmPersistentAttribute + extends SpecifiedOrmPersistentAttribute +{ + public GenericOrmPersistentAttribute(OrmPersistentType parent, XmlAttributeMapping xmlMapping) { + super(parent, xmlMapping); + } + + + // ********** access ********** + + /** + * JPA 1.0 does not support a specified access for attributes. + */ + @Override + public AccessType getSpecifiedAccess() { + return null; + } + + public void setSpecifiedAccess(AccessType access) { + throw new UnsupportedOperationException("A specified access is not supported in JPA 1.0: " + this); //$NON-NLS-1$ + } + + + // ********** validation ********** + + @Override + protected void validateAttribute(List<IMessage> messages, IReporter reporter) { + super.validateAttribute(messages, reporter); + if (this.javaPersistentAttribute != null) { + JavaPersistentType javaPersistentType = this.getOwningPersistentType().getJavaPersistentType(); + if ((javaPersistentType != null) && (javaPersistentType.getAttributeNamed(this.javaPersistentAttribute.getName()) == null)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENT_ATTRIBUTE_INHERITED_ATTRIBUTES_NOT_SUPPORTED, + new String[] { + this.getName(), + this.getOwningPersistentType().getMapping().getClass_() + }, + this.mapping, + this.mapping.getNameTextRange() + ) + ); + } + } + } + + @Override + protected JptValidator buildAttibuteValidator() { + return new GenericPersistentAttributeValidator(this, getJavaPersistentAttribute(), buildTextRangeResolver()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentType.java new file mode 100644 index 0000000000..9e28935ce4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPersistentType.java @@ -0,0 +1,1195 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Vector; +import org.eclipse.core.resources.IFile; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.BodySourceWriter; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.ClassName; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.StringTools; +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.CompositeListIterable; +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.SingleElementIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SnapshotCloneIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SuperListIterableWrapper; +import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyListIterator; +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.JavaPersistentType; +import org.eclipse.jpt.jpa.core.context.orm.EntityMappings; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMappingDefinition; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.context.orm.OrmReadOnlyPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.orm.OrmStructureNodes; +import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +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.MetamodelSourceType; +import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentType2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmPersistentType2_0; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; +import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.OrmPackage; +import org.eclipse.jpt.jpa.core.resource.orm.XmlAttributeMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlTypeMapping; +import org.eclipse.jpt.jpa.core.resource.xml.EmfTools; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.ReplaceEdit; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> persistent type:<ul> + * <li>mapping + * <li>access + * <li>attributes + * <li>super persistent type + * <li>Java persistent type + * </ul> + */ +public class GenericOrmPersistentType + extends AbstractOrmXmlContextNode + implements OrmPersistentType2_0 +{ + protected OrmTypeMapping mapping; // never null + + protected JavaPersistentType javaPersistentType; + + protected AccessType specifiedAccess; + protected AccessType defaultAccess; // never null + + protected final Vector<OrmPersistentAttribute> specifiedAttributes = new Vector<OrmPersistentAttribute>(); + protected final SpecifiedAttributeContainerAdapter specifiedAttributeContainerAdapter = new SpecifiedAttributeContainerAdapter(); + + protected final Vector<OrmReadOnlyPersistentAttribute> virtualAttributes = new Vector<OrmReadOnlyPersistentAttribute>(); + protected final VirtualAttributeContainerAdapter virtualAttributeContainerAdapter = new VirtualAttributeContainerAdapter(); + + protected PersistentType superPersistentType; + + protected String declaringTypeName; + + protected final MetamodelSourceType.Synchronizer metamodelSynchronizer; + + + public GenericOrmPersistentType(EntityMappings parent, XmlTypeMapping xmlTypeMapping) { + super(parent); + this.mapping = this.buildMapping(xmlTypeMapping); + // 'javaPersistentType' is resolved in the update + this.specifiedAccess = this.buildSpecifiedAccess(); + this.defaultAccess = AccessType.FIELD; // keep this non-null + this.initializeSpecifiedAttributes(); + this.metamodelSynchronizer = this.buildMetamodelSynchronizer(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.mapping.synchronizeWithResourceModel(); + this.syncJavaPersistentType(); + this.setSpecifiedAccess_(this.buildSpecifiedAccess()); + this.syncSpecifiedAttributes(); + this.synchronizeNodesWithResourceModel(this.getVirtualAttributes()); + } + + @Override + public void update() { + super.update(); + this.mapping.update(); + this.updateJavaPersistentType(); + this.setDefaultAccess(this.buildDefaultAccess()); + this.updateNodes(this.getSpecifiedAttributes()); + this.updateVirtualAttributes(); + this.setSuperPersistentType(this.buildSuperPersistentType()); + this.setDeclaringTypeName(this.buildDeclaringTypeName()); + } + + + // ********** mapping ********** + + public OrmTypeMapping getMapping() { + return this.mapping; + } + + public String getMappingKey() { + return this.mapping.getKey(); + } + + public void setMappingKey(String mappingKey) { + if (this.valuesAreDifferent(this.getMappingKey(), mappingKey)) { + this.setMappingKey_(mappingKey); + } + } + + protected void setMappingKey_(String mappingKey) { + OrmTypeMapping old = this.mapping; + OrmTypeMappingDefinition mappingDefinition = this.getMappingFileDefinition().getTypeMappingDefinition(mappingKey); + XmlTypeMapping xmlTypeMapping = mappingDefinition.buildResourceMapping(this.getResourceNodeFactory()); + this.mapping = this.buildMapping(xmlTypeMapping); + this.getEntityMappings().changeMapping(this, old, this.mapping); + this.firePropertyChanged(MAPPING_PROPERTY, old, this.mapping); + } + + protected OrmTypeMapping buildMapping(XmlTypeMapping xmlTypeMapping) { + OrmTypeMappingDefinition md = this.getMappingFileDefinition().getTypeMappingDefinition(xmlTypeMapping.getMappingKey()); + return md.buildContextMapping(this, xmlTypeMapping, this.getContextNodeFactory()); + } + + protected XmlTypeMapping getXmlTypeMapping() { + return this.mapping.getXmlTypeMapping(); + } + + public boolean isMapped() { + return true; + } + + + // ********** name ********** + + public String getName() { + return this.convertMappingClassName(this.mapping.getClass_()); + } + + public String getSimpleName(){ + String className = this.getName(); + return StringTools.stringIsEmpty(className) ? null : ClassName.getSimpleName(className); + } + + /** + * We clear out {@link #javaPersistentType} here because we cannot compare its name + * to the mapping's class name, since it may have been prefixed by the entity + * mappings package. + */ + public void mappingClassChanged(String oldClass, String newClass) { + this.firePropertyChanged(NAME_PROPERTY, this.convertMappingClassName(oldClass), this.convertMappingClassName(newClass)); + // clear out the Java type here, it will be rebuilt during "update" + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(null); + } + } + + /** + * Nested class names are specified with a <code>'$'</code> + * in <code>orm.xml</code>. + */ + protected String convertMappingClassName(String name) { + return (name == null) ? null : name.replace('$', '.'); + } + + + // ********** Java persistent type ********** + + public JavaPersistentType getJavaPersistentType() { + return this.javaPersistentType; + } + + protected void setJavaPersistentType(JavaPersistentType javaPersistentType) { + JavaPersistentType old = this.javaPersistentType; + this.javaPersistentType = javaPersistentType; + this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType); + } + + /** + * If the persistent type's mapping's class (name) changes during + * <em>sync</em>, the Java persistent type will be cleared out in + * {@link #mappingClassChanged(String, String)}. If we get here and + * the Java persistent type is still present, we can + * <em>sync</em> it. Of course, it might still be obsolete if the + * entity mappings's package has changed.... + * + * @see #updateJavaPersistentType() + */ + protected void syncJavaPersistentType() { + if (this.javaPersistentType != null) { + this.javaPersistentType.synchronizeWithResourceModel(); + } + } + + /** + * @see #syncJavaPersistentType() + */ + protected void updateJavaPersistentType() { + JavaResourcePersistentType resourceType = this.resolveJavaResourcePersistentType(); + if (resourceType == null) { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(null); + } + } else { + if (this.javaPersistentType == null) { + this.setJavaPersistentType(this.buildJavaPersistentType(resourceType)); + } else { + if (this.javaPersistentType.getResourcePersistentType() == resourceType) { + this.javaPersistentType.update(); + } else { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(this.buildJavaPersistentType(resourceType)); + } + } + } + } + + protected JavaResourcePersistentType resolveJavaResourcePersistentType() { + return this.getEntityMappings().resolveJavaResourcePersistentType(this.getName()); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + + // ********** access ********** + + public AccessType getAccess() { + return (this.specifiedAccess != null) ? this.specifiedAccess : this.defaultAccess; + } + + public AccessType getSpecifiedAccess() { + return this.specifiedAccess; + } + + public void setSpecifiedAccess(AccessType access) { + this.setSpecifiedAccess_(access); + this.getXmlTypeMapping().setAccess(AccessType.toOrmResourceModel(access)); + } + + protected void setSpecifiedAccess_(AccessType access) { + AccessType old = this.specifiedAccess; + this.specifiedAccess = access; + this.firePropertyChanged(SPECIFIED_ACCESS_PROPERTY, old, access); + } + + protected AccessType buildSpecifiedAccess() { + return AccessType.fromOrmResourceModel(this.getXmlTypeMapping().getAccess()); + } + + 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() { + if ( ! this.mapping.isMetadataComplete()) { + if (this.javaPersistentType != null) { + if (this.javaPersistentTypeHasSpecifiedAccess()) { + return this.javaPersistentType.getAccess(); + } + if (this.superPersistentType != null) { + return this.superPersistentType.getAccess(); + } + } + } + AccessType access = this.getMappingFileRoot().getAccess(); + return (access != null) ? access : AccessType.FIELD; // default to FIELD if no specified access found + } + + /** + * pre-condition: {@link #javaPersistentType} is not <code>null</code> + */ + protected boolean javaPersistentTypeHasSpecifiedAccess() { + return (this.javaPersistentType.getSpecifiedAccess() != null) || + this.javaPersistentType.hasAnyAnnotatedAttributes(); + } + + public AccessType getOwnerOverrideAccess() { + return this.getEntityMappings().getOverridePersistentTypeAccess(); + } + + public AccessType getOwnerDefaultAccess() { + return this.getEntityMappings().getDefaultPersistentTypeAccess(); + } + + + // ********** attributes ********** + + public ListIterator<OrmReadOnlyPersistentAttribute> attributes() { + return this.getAttributes().iterator(); + } + + @SuppressWarnings("unchecked") + public ListIterable<OrmReadOnlyPersistentAttribute> getAttributes() { + return new CompositeListIterable<OrmReadOnlyPersistentAttribute>(this.getReadOnlySpecifiedAttributes(), this.getVirtualAttributes()); + } + + public int attributesSize() { + return this.specifiedAttributesSize() + this.virtualAttributesSize(); + } + + public Iterator<String> attributeNames() { + return this.getAttributeNames().iterator(); + } + + public Iterable<String> getAttributeNames() { + return this.convertToNames(this.getAttributes()); + } + + public OrmReadOnlyPersistentAttribute getAttributeNamed(String attributeName) { + Iterator<OrmReadOnlyPersistentAttribute> stream = this.getAttributesNamed(attributeName).iterator(); + return stream.hasNext() ? stream.next() : null; + } + + public Iterator<ReadOnlyPersistentAttribute> allAttributes() { + return this.getAllAttributes().iterator(); + } + + public 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(); + } + + public Iterable<String> getAllAttributeNames() { + return this.convertToNames(this.getAllAttributes()); + } + + protected Iterable<OrmReadOnlyPersistentAttribute> getAttributesNamed(final String attributeName) { + return new FilteringIterable<OrmReadOnlyPersistentAttribute>(this.getAttributes()) { + @Override + protected boolean accept(OrmReadOnlyPersistentAttribute attribute) { + return Tools.valuesAreEqual(attributeName, attribute.getName()); + } + }; + } + + public ReadOnlyPersistentAttribute resolveAttribute(String attributeName) { + Iterator<OrmReadOnlyPersistentAttribute> attributes = this.getAttributesNamed(attributeName).iterator(); + if (attributes.hasNext()) { + OrmReadOnlyPersistentAttribute attribute = attributes.next(); + return attributes.hasNext() ? null /* more than one */: attribute; + } + // recurse + return (this.superPersistentType == null) ? null : this.superPersistentType.resolveAttribute(attributeName); + } + + protected Iterable<String> convertToNames(Iterable<? extends ReadOnlyPersistentAttribute> attributes) { + return new TransformationIterable<ReadOnlyPersistentAttribute, String>(attributes) { + @Override + protected String transform(ReadOnlyPersistentAttribute attribute) { + return attribute.getName(); + } + }; + } + + + // ********** attribute conversions ********** + + public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute) { + return this.convertAttributeToSpecified(virtualAttribute, virtualAttribute.getMappingKey()); + } + + public OrmPersistentAttribute convertAttributeToSpecified(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) { + if ( ! virtualAttribute.isVirtual()) { + throw new IllegalArgumentException("Attribute is already specified: " + virtualAttribute); //$NON-NLS-1$ + } + if (mappingKey == null) { + // this typically happens when the virtual attribute does not have a mapping + throw new IllegalArgumentException("Use convertAttributeToSpecified(OrmReadOnlyPersistentAttribute, String) instead and specify a mapping key"); //$NON-NLS-1$ + } + return this.convertAttributeToSpecified_(virtualAttribute, mappingKey); + } + + /** + * <em>Silently</em> remove the virtual attribute and add specified + * attribute before triggering an <em>update</em> or the dangling + * virtual attribute will be removed preemptively. + */ + protected OrmPersistentAttribute convertAttributeToSpecified_(OrmReadOnlyPersistentAttribute virtualAttribute, String mappingKey) { + // silently remove the virtual attribute + int virtualIndex = this.virtualAttributes.indexOf(virtualAttribute); + this.virtualAttributes.remove(virtualIndex); + virtualAttribute.dispose(); + + // silently add the specified attribute + OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey); + XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory()); + + OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping); + // we need to add the attribute to the right spot in the list - stupid spec... + int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute); + this.specifiedAttributes.add(specifiedIndex, specifiedAttribute); + + // this will trigger the initial update; + // no changes to either collection (virtual or specified) should be detected at this point + specifiedAttribute.getMapping().setName(virtualAttribute.getName()); + + // fire the list change events + this.fireItemRemoved(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute); + this.fireItemAdded(SPECIFIED_ATTRIBUTES_LIST, specifiedIndex, specifiedAttribute); + + // it should be safe to update the XML now + Attributes xmlAttributes = this.getXmlAttributesForUpdate(); + specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes); + // possibly a NOP, but needed when we trigger the creation of a new 'attributes' + this.getXmlTypeMapping().setAttributes(xmlAttributes); + + // copy over the specified access(?) + AccessType oldAccess = virtualAttribute.getJavaPersistentAttribute().getSpecifiedAccess(); + if (oldAccess != null) { + specifiedAttribute.setSpecifiedAccess(oldAccess); + } + return specifiedAttribute; + } + + // TODO this is used only by our tests... + // we cannot delegate to getAttributeNamed(String).convertToSpecified() + // because the tests use this method to add "orphan" xml attributes (that + // do not have a corresponding java attribute :( ) + public OrmPersistentAttribute addSpecifiedAttribute(String mappingKey, String attributeName) { + // force the creation of an empty xml attribute container beforehand or it will trigger + // a sync and, if we do this after adding the attribute, clear out our context attributes + Attributes xmlAttributes = this.getXmlAttributesForUpdate(); + this.getXmlTypeMapping().setAttributes(xmlAttributes); // possibly a NOP + + OrmAttributeMappingDefinition md = this.getMappingFileDefinition().getAttributeMappingDefinition(mappingKey); + XmlAttributeMapping xmlMapping = md.buildResourceMapping(this.getResourceNodeFactory()); + + OrmPersistentAttribute specifiedAttribute = this.buildSpecifiedAttribute(xmlMapping); + // we need to add the attribute to the right spot in the list - stupid spec... + int specifiedIndex = this.getSpecifiedAttributeInsertionIndex(specifiedAttribute); + // the virtual attributes list should remain unchanged since the specified attribute has no name + this.addItemToList(specifiedIndex, specifiedAttribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST); + specifiedAttribute.getMapping().addXmlAttributeMappingTo(xmlAttributes); + + // this will trigger the update of the virtual attributes list + specifiedAttribute.getMapping().setName(attributeName); + + return specifiedAttribute; + } + + protected int getSpecifiedAttributeInsertionIndex(OrmPersistentAttribute attribute) { + return CollectionTools.insertionIndexOf(this.specifiedAttributes, attribute, this.getAttributeComparator()); + } + + protected Comparator<OrmPersistentAttribute> getAttributeComparator() { + return ATTRIBUTE_COMPARATOR; + } + + protected static final Comparator<OrmPersistentAttribute> ATTRIBUTE_COMPARATOR = + new Comparator<OrmPersistentAttribute>() { + public int compare(OrmPersistentAttribute attribute1, OrmPersistentAttribute attribute2) { + int seq1 = attribute1.getMapping().getXmlSequence(); + int seq2 = attribute2.getMapping().getXmlSequence(); + return (seq1 == seq2) ? 0 : (seq1 < seq2) ? -1 : 1; + } + }; + + /** + * <em>Silently</em> add the new virtual attribute before removing the + * specified attribute, or the <em>update</em> will discover the missing + * virtual attribute and add it preemptively. + */ + public OrmReadOnlyPersistentAttribute convertAttributeToVirtual(OrmPersistentAttribute specifiedAttribute) { + if (specifiedAttribute.isVirtual()) { + throw new IllegalArgumentException("Attribute is already virtual: " + specifiedAttribute); //$NON-NLS-1$ + } + + int virtualIndex = this.virtualAttributes.size(); + OrmReadOnlyPersistentAttribute virtualAttribute = null; + // make sure the corresponding resource Java attribute actually exists in the *current* type; + // do *not* take the context Java attribute directly from the specified ORM + // attribute we are converting since it may have come from a superclass; + // instead, use its resource Java attribute (which will match both name and access type, + // but we still need to check its parent type) + JavaResourcePersistentAttribute javaResourceAttribute = specifiedAttribute.getJavaResourcePersistentAttribute(); + if ((javaResourceAttribute != null) && this.javaResourceAttributeWillBeVirtual(javaResourceAttribute, specifiedAttribute)) { + virtualAttribute = this.buildVirtualAttribute(javaResourceAttribute); + this.virtualAttributes.add(virtualIndex, virtualAttribute); + } + + this.removeSpecifiedAttribute(specifiedAttribute); // trigger update + + if (virtualAttribute != null) { + this.fireItemAdded(VIRTUAL_ATTRIBUTES_LIST, virtualIndex, virtualAttribute); + } + return virtualAttribute; + } + + /** + * Return whether the specified Java resource attribute will be a + * <em>virtual</em> attribute when the specified specified attribute is + * removed from the type. The Java resource attribute must be among the + * valid Java resource attributes and it must not correspond to any of the + * remaining specified attributes. + */ + protected boolean javaResourceAttributeWillBeVirtual(JavaResourcePersistentAttribute javaResourceAttribute, OrmPersistentAttribute specifiedAttributeToBeRemoved) { + return CollectionTools.contains(this.getJavaResourceAttributes(), javaResourceAttribute) && + (this.getSpecifiedAttributeFor(javaResourceAttribute, specifiedAttributeToBeRemoved) == null); + } + + + // ********** xml attributes ********** + + /** + * Return <code>null</code> if the <code>attributes</code> element is missing. + */ + protected Attributes getXmlAttributes() { + return this.getXmlTypeMapping().getAttributes(); + } + + /** + * Build a new <code>attributes</code> element if it is not present; + * but do <em>not</em> add it to the XML type mapping. Callers will have + * to add it to the XML type mapping when appropriate. + */ + protected Attributes getXmlAttributesForUpdate() { + Attributes xmlAttributes = this.getXmlAttributes(); + return (xmlAttributes != null) ? xmlAttributes : this.buildXmlAttributes(); + } + + protected Attributes buildXmlAttributes() { + return EmfTools.create(this.getResourceNodeFactory(), OrmPackage.eINSTANCE.getAttributes(), Attributes.class); + } + + protected void removeXmlAttributesIfUnset() { + if (this.getXmlAttributes().isUnset()) { + this.getXmlTypeMapping().setAttributes(null); + } + } + + + // ********** specified attributes ********** + + public ListIterator<OrmPersistentAttribute> specifiedAttributes() { + return this.getSpecifiedAttributes().iterator(); + } + + protected ListIterable<OrmPersistentAttribute> getSpecifiedAttributes() { + return new LiveCloneListIterable<OrmPersistentAttribute>(this.specifiedAttributes); + } + + protected ListIterable<OrmReadOnlyPersistentAttribute> getReadOnlySpecifiedAttributes() { + return new SuperListIterableWrapper<OrmReadOnlyPersistentAttribute>(this.getSpecifiedAttributes()); + } + + public int specifiedAttributesSize() { + return this.specifiedAttributes.size(); + } + + protected void removeSpecifiedAttribute(OrmPersistentAttribute attribute) { + this.removeSpecifiedAttribute_(attribute); + attribute.getMapping().removeXmlAttributeMappingFrom(this.getXmlAttributes()); + this.removeXmlAttributesIfUnset(); + } + + public void changeMapping(OrmPersistentAttribute attribute, OrmAttributeMapping oldMapping, OrmAttributeMapping newMapping) { + // keep the context model in sync with each change to the resource model + int sourceIndex = this.specifiedAttributes.indexOf(attribute); + this.specifiedAttributes.remove(sourceIndex); + oldMapping.removeXmlAttributeMappingFrom(this.getXmlAttributes()); + + int targetIndex = this.getSpecifiedAttributeInsertionIndex(attribute); + this.specifiedAttributes.add(targetIndex, attribute); + newMapping.addXmlAttributeMappingTo(this.getXmlAttributes()); + + oldMapping.initializeOn(newMapping); + + this.fireItemMoved(SPECIFIED_ATTRIBUTES_LIST, targetIndex, sourceIndex); + } + + protected void initializeSpecifiedAttributes() { + for (XmlAttributeMapping xmlMapping : this.getXmlAttributeMappings()) { + this.specifiedAttributes.add(this.buildSpecifiedAttribute(xmlMapping)); + } + } + + protected Iterable<XmlAttributeMapping> getXmlAttributeMappings() { + Attributes xmlAttributes = this.getXmlAttributes(); + return (xmlAttributes != null) ? xmlAttributes.getAttributeMappings() : EmptyIterable.<XmlAttributeMapping>instance(); + } + + protected OrmPersistentAttribute buildSpecifiedAttribute(XmlAttributeMapping xmlMapping) { + return this.getContextNodeFactory().buildOrmPersistentAttribute(this, xmlMapping); + } + + protected void syncSpecifiedAttributes() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedAttributeContainerAdapter); + } + + protected void moveSpecifiedAttribute_(int index, OrmPersistentAttribute attribute) { + this.moveItemInList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST); + } + + protected void addSpecifiedAttribute_(int index, XmlAttributeMapping xmlMapping) { + OrmPersistentAttribute attribute = this.buildSpecifiedAttribute(xmlMapping); + this.addItemToList(index, attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST); + } + + protected void removeSpecifiedAttribute_(OrmPersistentAttribute attribute) { + this.removeItemFromList(attribute, this.specifiedAttributes, SPECIFIED_ATTRIBUTES_LIST); + } + + /** + * specified attribute container adapter + */ + protected class SpecifiedAttributeContainerAdapter + implements ContextContainerTools.Adapter<OrmPersistentAttribute, XmlAttributeMapping> + { + public Iterable<OrmPersistentAttribute> getContextElements() { + return GenericOrmPersistentType.this.getSpecifiedAttributes(); + } + public Iterable<XmlAttributeMapping> getResourceElements() { + return GenericOrmPersistentType.this.getXmlAttributeMappings(); + } + public XmlAttributeMapping getResourceElement(OrmPersistentAttribute contextElement) { + return contextElement.getMapping().getXmlAttributeMapping(); + } + public void moveContextElement(int index, OrmPersistentAttribute element) { + GenericOrmPersistentType.this.moveSpecifiedAttribute_(index, element); + } + public void addContextElement(int index, XmlAttributeMapping resourceElement) { + GenericOrmPersistentType.this.addSpecifiedAttribute_(index, resourceElement); + } + public void removeContextElement(OrmPersistentAttribute element) { + GenericOrmPersistentType.this.removeSpecifiedAttribute_(element); + } + } + + + // ********** virtual attributes ********** + + public ListIterator<OrmReadOnlyPersistentAttribute> virtualAttributes() { + return this.getVirtualAttributes().iterator(); + } + + public ListIterable<OrmReadOnlyPersistentAttribute> getVirtualAttributes() { + return new LiveCloneListIterable<OrmReadOnlyPersistentAttribute>(this.virtualAttributes); + } + + public int virtualAttributesSize() { + return this.virtualAttributes.size(); + } + + protected void updateVirtualAttributes() { + ContextContainerTools.update(this.virtualAttributeContainerAdapter); + } + + /** + * Return all the Java resource attributes that have the appropriate access + * and do not have a corresponding <code>orm.xml</code> mapping currently + * specified in the <code>orm.xml</code> persistent type. + */ + protected Iterable<JavaResourcePersistentAttribute> getVirtualJavaResourceAttributes() { + return new FilteringIterable<JavaResourcePersistentAttribute>(this.getJavaResourceAttributes()) { + @Override + protected boolean accept(JavaResourcePersistentAttribute javaResourceAttribute) { + return GenericOrmPersistentType.this.javaResourceAttributeIsVirtual(javaResourceAttribute); + } + }; + } + + protected Iterable<JavaResourcePersistentAttribute> getJavaResourceAttributes() { + return CollectionTools.iterable(this.javaResourceAttributes()); + } + + /** + * Return the Java resource attributes with the appropriate access type. + */ + protected Iterator<JavaResourcePersistentAttribute> javaResourceAttributes() { + JavaResourcePersistentType javaResourceType = this.getJavaResourceType(); + return (javaResourceType != null) ? + javaResourceType.persistableAttributes(this.getVirtualJavaAccess().getJavaAccessType()) : + EmptyListIterator.<JavaResourcePersistentAttribute>instance(); + } + + protected JavaResourcePersistentType getJavaResourceType() { + return (this.javaPersistentType == null) ? null : this.javaPersistentType.getResourcePersistentType(); + } + + /** + * Return the access type that determines which Java attributes are to be + * used for the <code>orm.xml</code> type's <em>virtual</em> attributes. + */ + protected AccessType getVirtualJavaAccess() { + if (this.specifiedAccess != null) { + return this.specifiedAccess; + } + if (this.mapping.isMetadataComplete()) { + return this.defaultAccess; + } + AccessType javaAccess = this.javaPersistentType.getSpecifiedAccess(); + return (javaAccess != null) ? javaAccess : this.defaultAccess; + } + + protected boolean javaResourceAttributeIsVirtual(JavaResourcePersistentAttribute javaResourceAttribute) { + return this.getSpecifiedAttributeFor(javaResourceAttribute) == null; + } + + protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourcePersistentAttribute javaResourceAttribute) { + return this.getSpecifiedAttributeFor(javaResourceAttribute, null); + } + + /** + * Return the specified attribute corresponding to the specified Java + * resource attribute, ignoring the specified excluded attribute (since + * there can be more than one specified attribute per Java resource + * attribute; albeit erroneously). + */ + protected OrmPersistentAttribute getSpecifiedAttributeFor(JavaResourcePersistentAttribute javaResourceAttribute, OrmPersistentAttribute exclude) { + for (OrmPersistentAttribute ormAttribute : this.getSpecifiedAttributes()) { + if (ormAttribute == exclude) { + continue; // skip + } + if (ormAttribute.getJavaResourcePersistentAttribute() == javaResourceAttribute) { + return ormAttribute; + } + } + return null; + } + + protected void moveVirtualAttribute(int index, OrmReadOnlyPersistentAttribute virtualAttribute) { + this.moveItemInList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST); + } + + protected void addVirtualAttribute(int index, JavaResourcePersistentAttribute javaResourceAttribute) { + OrmReadOnlyPersistentAttribute virtualAttribute = this.buildVirtualAttribute(javaResourceAttribute); + this.addItemToList(index, virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST); + } + + protected OrmReadOnlyPersistentAttribute buildVirtualAttribute(JavaResourcePersistentAttribute javaResourceAttribute) { + return this.getContextNodeFactory().buildVirtualOrmPersistentAttribute(this, javaResourceAttribute); + } + + protected void removeVirtualAttribute(OrmReadOnlyPersistentAttribute virtualAttribute) { + virtualAttribute.dispose(); + this.removeItemFromList(virtualAttribute, this.virtualAttributes, VIRTUAL_ATTRIBUTES_LIST); + } + + /** + * virtual attribute container adapter + */ + protected class VirtualAttributeContainerAdapter + implements ContextContainerTools.Adapter<OrmReadOnlyPersistentAttribute, JavaResourcePersistentAttribute> + { + public Iterable<OrmReadOnlyPersistentAttribute> getContextElements() { + return GenericOrmPersistentType.this.getVirtualAttributes(); + } + public Iterable<JavaResourcePersistentAttribute> getResourceElements() { + return GenericOrmPersistentType.this.getVirtualJavaResourceAttributes(); + } + public JavaResourcePersistentAttribute getResourceElement(OrmReadOnlyPersistentAttribute contextElement) { + return contextElement.getJavaResourcePersistentAttribute(); + } + public void moveContextElement(int index, OrmReadOnlyPersistentAttribute element) { + GenericOrmPersistentType.this.moveVirtualAttribute(index, element); + } + public void addContextElement(int index, JavaResourcePersistentAttribute resourceElement) { + GenericOrmPersistentType.this.addVirtualAttribute(index, resourceElement); + } + public void removeContextElement(OrmReadOnlyPersistentAttribute element) { + GenericOrmPersistentType.this.removeVirtualAttribute(element); + } + } + + + // ********** super persistent type ********** + + public PersistentType getSuperPersistentType() { + return this.superPersistentType; + } + + protected void setSuperPersistentType(PersistentType persistentType) { + PersistentType old = this.superPersistentType; + this.superPersistentType = persistentType; + this.firePropertyChanged(SUPER_PERSISTENT_TYPE_PROPERTY, old, persistentType); + } + + protected PersistentType buildSuperPersistentType() { + PersistentType spt = this.buildSuperPersistentType_(); + if (spt == null) { + return null; + } + // check for circular inheritance + return CollectionTools.contains(spt.inheritanceHierarchy(), this) ? null : spt; + } + + protected PersistentType buildSuperPersistentType_() { + return (this.javaPersistentType == null) ? null : this.javaPersistentType.getSuperPersistentType(); + } + + + // ********** 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(); + } + }; + } + + + // ********** declaring type name ********** + + public String getDeclaringTypeName() { + return this.declaringTypeName; + } + + protected void setDeclaringTypeName(String name) { + String old = this.declaringTypeName; + this.declaringTypeName = name; + this.firePropertyChanged(DECLARING_TYPE_NAME_PROPERTY, old, name); + } + + protected String buildDeclaringTypeName() { + return this.isJpa2_0Compatible() ? this.buildDeclaringTypeName_() : null; + } + + protected String buildDeclaringTypeName_() { + return (this.javaPersistentType == null) ? + null : ((JavaPersistentType2_0) this.javaPersistentType).getDeclaringTypeName(); + } + + + // ********** metamodel ********** + + protected MetamodelSourceType.Synchronizer buildMetamodelSynchronizer() { + return this.isJpa2_0Compatible() ? + this.getJpaFactory2_0().buildMetamodelSynchronizer(this) : + null; + } + + public IFile getMetamodelFile() { + return (this.javaPersistentType == null) ? null : this.metamodelSynchronizer.getFile(); + } + + public void initializeMetamodel() { + // do nothing - probably shouldn't be called... + } + + public boolean isManaged() { + return true; + } + + /** + * All <code>orm.xml</code> persistent types must be able to generate a static metamodel + * because 1.0 <code>orm.xml</code> files can be referenced from 2.0 persistence.xml files. + */ + public void synchronizeMetamodel(Map<String, Collection<MetamodelSourceType>> memberTypeTree) { + if (this.javaPersistentType != null) { + this.metamodelSynchronizer.synchronize(memberTypeTree); + } + } + + public void printBodySourceOn(BodySourceWriter pw, Map<String, Collection<MetamodelSourceType>> memberTypeTree) { + if (this.javaPersistentType != null) { + this.metamodelSynchronizer.printBodySourceOn(pw, memberTypeTree); + } + } + + public void disposeMetamodel() { + // do nothing - probably shouldn't be called... + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return OrmStructureNodes.PERSISTENT_TYPE_ID; + } + + public JpaStructureNode getStructureNode(int textOffset) { + for (OrmPersistentAttribute attribute : this.getSpecifiedAttributes()) { + if (attribute.contains(textOffset)) { + return attribute; + } + } + return this; + } + + public TextRange getSelectionTextRange() { + return this.mapping.getSelectionTextRange(); + } + + public void dispose() { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + } + for (OrmReadOnlyPersistentAttribute virtualAttribute : this.getVirtualAttributes()) { + virtualAttribute.dispose(); + } + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getOverridePersistentTypeAccess() { + if (this.specifiedAccess != null) { + return this.specifiedAccess; + } + + if (this.superPersistentType instanceof OrmPersistentType) { + AccessType accessType = ((OrmPersistentType) this.superPersistentType).getSpecifiedAccess(); + if (accessType != null) { + return accessType; + } + } + + if (this.mapping.isMetadataComplete()) { + AccessType accessType = this.getOwnerDefaultAccess(); + if (accessType != null) { + return accessType; + } + } + + // no override access type + return null; + } + + public AccessType getDefaultPersistentTypeAccess() { + if (this.superPersistentType instanceof OrmPersistentType) { + AccessType accessType = ((OrmPersistentType) this.superPersistentType).getDefaultAccess(); + if (accessType != null) { + return accessType; + } + } + + return this.getOwnerDefaultAccess(); + } + + + //*********** refactoring *********** + + public Iterable<DeleteEdit> createDeleteTypeEdits(IType type) { + return this.isFor(type.getFullyQualifiedName('.')) ? + new SingleElementIterable<DeleteEdit>(this.mapping.createDeleteEdit()) : + EmptyIterable.<DeleteEdit>instance(); + } + + @SuppressWarnings("unchecked") + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return new CompositeIterable<ReplaceEdit>( + this.mapping.createRenameTypeEdits(originalType, newName), + this.createSpecifiedAttributesRenameTypeEdits(originalType, newName) + ); + } + + protected Iterable<ReplaceEdit> createSpecifiedAttributesRenameTypeEdits(final IType originalType, final String newName) { + return new CompositeIterable<ReplaceEdit>( + new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) { + @Override + protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) { + return persistentAttribute.createRenameTypeEdits(originalType, newName); + } + } + ); + } + + @SuppressWarnings("unchecked") + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return new CompositeIterable<ReplaceEdit>( + this.mapping.createMoveTypeEdits(originalType, newPackage), + this.createSpecifiedAttributesMoveTypeEdits(originalType, newPackage) + ); + } + + protected Iterable<ReplaceEdit> createSpecifiedAttributesMoveTypeEdits(final IType originalType, final IPackageFragment newPackage) { + return new CompositeIterable<ReplaceEdit>( + new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) { + @Override + protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) { + return persistentAttribute.createMoveTypeEdits(originalType, newPackage); + } + } + ); + } + + @SuppressWarnings("unchecked") + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return new CompositeIterable<ReplaceEdit>( + this.mapping.createRenamePackageEdits(originalPackage, newName), + this.createSpecifiedAttributesRenamePackageEdits(originalPackage, newName) + ); + } + + protected Iterable<ReplaceEdit> createSpecifiedAttributesRenamePackageEdits(final IPackageFragment originalPackage, final String newName) { + return new CompositeIterable<ReplaceEdit>( + new TransformationIterable<OrmPersistentAttribute, Iterable<ReplaceEdit>>(this.getSpecifiedAttributes()) { + @Override + protected Iterable<ReplaceEdit> transform(OrmPersistentAttribute persistentAttribute) { + return persistentAttribute.createRenamePackageEdits(originalPackage, newName); + } + } + ); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateClass(messages); + this.validateMapping(messages, reporter); + this.validateAttributes(messages, reporter); + } + + protected void validateClass(List<IMessage> messages) { + if (this.javaPersistentType == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENT_TYPE_UNRESOLVED_CLASS, + new String[] {this.getName()}, + this, + this.mapping.getClassTextRange() + ) + ); + } + } + + protected void validateMapping(List<IMessage> messages, IReporter reporter) { + try { + this.mapping.validate(messages, reporter); + } catch(Throwable t) { + JptJpaCorePlugin.log(t); + } + } + + protected void validateAttributes(List<IMessage> messages, IReporter reporter) { + for (Iterator<OrmReadOnlyPersistentAttribute> stream = this.attributes(); stream.hasNext(); ) { + this.validateAttribute(stream.next(), messages, reporter); + } + } + + protected void validateAttribute(OrmReadOnlyPersistentAttribute attribute, List<IMessage> messages, IReporter reporter) { + try { + attribute.validate(messages, reporter); + } catch(Throwable t) { + JptJpaCorePlugin.log(t); + } + } + + public TextRange getValidationTextRange() { + return this.mapping.getValidationTextRange(); + } + + + // ********** misc ********** + + @Override + public EntityMappings getParent() { + return (EntityMappings) super.getParent(); + } + + protected EntityMappings getEntityMappings() { + return this.getParent(); + } + + public String getDefaultPackage() { + return this.getEntityMappings().getPackage(); + } + + public boolean isFor(String typeName) { + String name = this.getName(); + if (name == null) { + return false; + } + if (name.equals(typeName)) { + return true; + } + String defaultPackage = this.getDefaultPackage(); + if (defaultPackage == null) { + return false; + } + return (defaultPackage + '.' + name).equals(typeName); + } + + public boolean isIn(IPackageFragment packageFragment) { + String packageName = this.getPackageName(); + if (Tools.valuesAreEqual(packageName, packageFragment.getElementName())) { + return true; + } + String defaultPackage = this.getDefaultPackage(); + if (defaultPackage == null) { + return false; + } + packageName = (packageName == null) ? defaultPackage : defaultPackage + '.' + packageName; + return packageName.equals(packageFragment.getElementName()); + } + + protected String getPackageName() { + String className = this.getName(); + if (className == null) { + return null; + } + int lastPeriod = className.lastIndexOf('.'); + return (lastPeriod == -1) ? null : className.substring(0, lastPeriod); + } + + public boolean contains(int textOffset) { + return this.mapping.containsOffset(textOffset); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.getName()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..9761ef1cce --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmPrimaryKeyJoinColumn.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.ReadOnlyPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmNamedColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmPrimaryKeyJoinColumnTextRangeResolver; +import org.eclipse.jpt.jpa.core.resource.orm.XmlPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.db.Column; +import org.eclipse.jpt.jpa.db.Table; + +/** + * <code>orm.xml</code> primary key join column + */ +public class GenericOrmPrimaryKeyJoinColumn + extends AbstractOrmNamedColumn<XmlPrimaryKeyJoinColumn, OrmBaseJoinColumn.Owner> + implements OrmPrimaryKeyJoinColumn +{ + /** @see org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmNamedColumn#AbstractOrmNamedColumn(XmlContextNode, org.eclipse.jpt.jpa.core.context.orm.OrmNamedColumn.Owner, org.eclipse.jpt.jpa.core.resource.orm.AbstractXmlNamedColumn) */ + protected /* final */ XmlPrimaryKeyJoinColumn xmlColumn; // null for default pk join columns + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericOrmPrimaryKeyJoinColumn(XmlContextNode parent, OrmBaseJoinColumn.Owner owner, XmlPrimaryKeyJoinColumn xmlColumn) { + super(parent, owner, xmlColumn); + this.specifiedReferencedColumnName = this.buildSpecifiedReferencedColumnName(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedReferencedColumnName_(this.buildSpecifiedReferencedColumnName()); + } + + @Override + public void update() { + super.update(); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** XML column ********** + + @Override + public XmlPrimaryKeyJoinColumn getXmlColumn() { + return this.xmlColumn; + } + + @Override + protected void setXmlColumn(XmlPrimaryKeyJoinColumn xmlColumn) { + this.xmlColumn = xmlColumn; + } + + /** + * primary key join columns are part of a collection; + * the 'primary-key-join-column' element will be removed/added + * when the XML join column is removed from/added to + * the owner's collection + */ + @Override + protected XmlPrimaryKeyJoinColumn buildXmlColumn() { + throw new IllegalStateException("XML primary key join column is missing"); //$NON-NLS-1$ + } + + /** + * @see #buildXmlColumn() + */ + @Override + protected void removeXmlColumn() { + // do nothing + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + public void setSpecifiedReferencedColumnName(String name) { + this.setSpecifiedReferencedColumnName_(name); + this.xmlColumn.setReferencedColumnName(name); + } + + protected void setSpecifiedReferencedColumnName_(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return (this.xmlColumn == null) ? null : this.xmlColumn.getReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + // TODO not correct when we start supporting + // primary key join columns in 1-1 mappings + protected String buildDefaultReferencedColumnName() { + return this.buildDefaultName(); + } + + + // ********** database stuff ********** + + public Table getReferencedColumnDbTable() { + return this.owner.getReferencedColumnDbTable(); + } + + protected Column getReferencedDbColumn() { + Table table = this.getReferencedColumnDbTable(); + return (table == null) ? null : table.getColumnForIdentifier(this.getReferencedColumnName()); + } + + public boolean referencedColumnIsResolved() { + return this.getReferencedDbColumn() != null; + } + + + // ********** misc ********** + + public void initializeFrom(ReadOnlyPrimaryKeyJoinColumn oldColumn) { + super.initializeFrom(oldColumn); + this.setSpecifiedReferencedColumnName(oldColumn.getSpecifiedReferencedColumnName()); + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + @Override + public String getTable() { + return this.owner.getDefaultTableName(); + } + + @Override + protected NamedColumnTextRangeResolver buildTextRangeResolver() { + return new OrmPrimaryKeyJoinColumnTextRangeResolver(this); + } + + public TextRange getReferencedColumnNameTextRange() { + return this.getTextRange(this.xmlColumn.getReferencedColumnNameTextRange()); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java new file mode 100644 index 0000000000..c4858f9420 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java @@ -0,0 +1,366 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable; +import org.eclipse.jpt.common.utility.internal.iterables.ListIterable; +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable; +import org.eclipse.jpt.jpa.core.context.NamedNativeQuery; +import org.eclipse.jpt.jpa.core.context.NamedQuery; +import org.eclipse.jpt.jpa.core.context.Query; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmNamedNativeQuery; +import org.eclipse.jpt.jpa.core.context.orm.OrmNamedQuery; +import org.eclipse.jpt.jpa.core.context.orm.OrmQuery; +import org.eclipse.jpt.jpa.core.context.orm.OrmQueryContainer; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +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.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedNativeQuery; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedQuery; +import org.eclipse.jpt.jpa.core.resource.orm.XmlQueryContainer; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> query container + */ +public class GenericOrmQueryContainer + extends AbstractOrmXmlContextNode + implements OrmQueryContainer +{ + protected final XmlQueryContainer xmlQueryContainer; + + protected final Vector<OrmNamedQuery> namedQueries = new Vector<OrmNamedQuery>(); + protected NamedQueryContainerAdapter namedQueryContainerAdapter = new NamedQueryContainerAdapter(); + + protected final Vector<OrmNamedNativeQuery> namedNativeQueries = new Vector<OrmNamedNativeQuery>(); + protected NamedNativeQueryContainerAdapter namedNativeQueryContainerAdapter = new NamedNativeQueryContainerAdapter(); + + + public GenericOrmQueryContainer(XmlContextNode parent, XmlQueryContainer xmlQueryContainer) { + super(parent); + this.xmlQueryContainer = xmlQueryContainer; + this.initializeNamedQueries(); + this.initializeNamedNativeQueries(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncNamedQueries(); + this.syncNamedNativeQueries(); + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getNamedQueries()); + this.updateNodes(this.getNamedNativeQueries()); + } + + + // ********** named queries ********** + + public ListIterator<OrmNamedQuery> namedQueries() { + return this.getNamedQueries().iterator(); + } + + protected ListIterable<OrmNamedQuery> getNamedQueries() { + return new LiveCloneListIterable<OrmNamedQuery>(this.namedQueries); + } + + public int namedQueriesSize() { + return this.namedQueries.size(); + } + + public OrmNamedQuery addNamedQuery() { + return this.addNamedQuery(this.namedQueries.size()); + } + + public OrmNamedQuery addNamedQuery(int index) { + XmlNamedQuery xmlQuery = this.buildXmlNamedQuery(); + OrmNamedQuery query = this.addNamedQuery_(index, xmlQuery); + this.xmlQueryContainer.getNamedQueries().add(index, xmlQuery); + return query; + } + + protected XmlNamedQuery buildXmlNamedQuery() { + return OrmFactory.eINSTANCE.createXmlNamedQuery(); + } + + public void removeNamedQuery(NamedQuery namedQuery) { + this.removeNamedQuery(this.namedQueries.indexOf(namedQuery)); + } + + public void removeNamedQuery(int index) { + this.removeNamedQuery_(index); + this.xmlQueryContainer.getNamedQueries().remove(index); + } + + protected void removeNamedQuery_(int index) { + this.removeItemFromList(index, this.namedQueries, NAMED_QUERIES_LIST); + } + + public void moveNamedQuery(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.namedQueries, NAMED_QUERIES_LIST); + this.xmlQueryContainer.getNamedQueries().move(targetIndex, sourceIndex); + } + + protected void initializeNamedQueries() { + for (XmlNamedQuery xmlQuery : this.getXmlNamedQueries()) { + this.namedQueries.add(this.buildNamedQuery(xmlQuery)); + } + } + + protected OrmNamedQuery buildNamedQuery(XmlNamedQuery xmlNamedQuery) { + return this.getContextNodeFactory().buildOrmNamedQuery(this, xmlNamedQuery); + } + + protected void syncNamedQueries() { + ContextContainerTools.synchronizeWithResourceModel(this.namedQueryContainerAdapter); + } + + protected Iterable<XmlNamedQuery> getXmlNamedQueries() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlNamedQuery>(this.xmlQueryContainer.getNamedQueries()); + } + + protected void moveNamedQuery_(int index, OrmNamedQuery namedQuery) { + this.moveItemInList(index, namedQuery, this.namedQueries, NAMED_QUERIES_LIST); + } + + protected OrmNamedQuery addNamedQuery_(int index, XmlNamedQuery xmlNamedQuery) { + OrmNamedQuery query = this.buildNamedQuery(xmlNamedQuery); + this.addItemToList(index, query, this.namedQueries, NAMED_QUERIES_LIST); + return query; + } + + protected void removeNamedQuery_(OrmNamedQuery namedQuery) { + this.removeNamedQuery_(this.namedQueries.indexOf(namedQuery)); + } + + /** + * named query container adapter + */ + protected class NamedQueryContainerAdapter + implements ContextContainerTools.Adapter<OrmNamedQuery, XmlNamedQuery> + { + public Iterable<OrmNamedQuery> getContextElements() { + return GenericOrmQueryContainer.this.getNamedQueries(); + } + public Iterable<XmlNamedQuery> getResourceElements() { + return GenericOrmQueryContainer.this.getXmlNamedQueries(); + } + public XmlNamedQuery getResourceElement(OrmNamedQuery contextElement) { + return contextElement.getXmlQuery(); + } + public void moveContextElement(int index, OrmNamedQuery element) { + GenericOrmQueryContainer.this.moveNamedQuery_(index, element); + } + public void addContextElement(int index, XmlNamedQuery resourceElement) { + GenericOrmQueryContainer.this.addNamedQuery_(index, resourceElement); + } + public void removeContextElement(OrmNamedQuery element) { + GenericOrmQueryContainer.this.removeNamedQuery_(element); + } + } + + + // ********** named native queries ********** + + public ListIterator<OrmNamedNativeQuery> namedNativeQueries() { + return this.getNamedNativeQueries().iterator(); + } + + protected ListIterable<OrmNamedNativeQuery> getNamedNativeQueries() { + return new LiveCloneListIterable<OrmNamedNativeQuery>(this.namedNativeQueries); + } + + public int namedNativeQueriesSize() { + return this.namedNativeQueries.size(); + } + + public OrmNamedNativeQuery addNamedNativeQuery() { + return this.addNamedNativeQuery(this.namedNativeQueries.size()); + } + + public OrmNamedNativeQuery addNamedNativeQuery(int index) { + XmlNamedNativeQuery xmlQuery = this.buildXmlNamedNativeQuery(); + OrmNamedNativeQuery query = this.addNamedNativeQuery_(index, xmlQuery); + this.xmlQueryContainer.getNamedNativeQueries().add(index, xmlQuery); + return query; + } + + protected XmlNamedNativeQuery buildXmlNamedNativeQuery() { + return OrmFactory.eINSTANCE.createXmlNamedNativeQuery(); + } + + public void removeNamedNativeQuery(NamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + public void removeNamedNativeQuery(int index) { + this.removeNamedNativeQuery_(index); + this.xmlQueryContainer.getNamedNativeQueries().remove(index); + } + + protected void removeNamedNativeQuery_(int index) { + this.removeItemFromList(index, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + public void moveNamedNativeQuery(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + this.xmlQueryContainer.getNamedNativeQueries().move(targetIndex, sourceIndex); + } + + protected void initializeNamedNativeQueries() { + for (XmlNamedNativeQuery xmlQuery : this.getXmlNamedNativeQueries()) { + this.namedNativeQueries.add(this.buildNamedNativeQuery(xmlQuery)); + } + } + + protected OrmNamedNativeQuery buildNamedNativeQuery(XmlNamedNativeQuery xmlNamedNativeQuery) { + return this.getContextNodeFactory().buildOrmNamedNativeQuery(this, xmlNamedNativeQuery); + } + + protected void syncNamedNativeQueries() { + ContextContainerTools.synchronizeWithResourceModel(this.namedNativeQueryContainerAdapter); + } + + protected Iterable<XmlNamedNativeQuery> getXmlNamedNativeQueries() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlNamedNativeQuery>(this.xmlQueryContainer.getNamedNativeQueries()); + } + + protected void moveNamedNativeQuery_(int index, OrmNamedNativeQuery namedNativeQuery) { + this.moveItemInList(index, namedNativeQuery, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + } + + protected OrmNamedNativeQuery addNamedNativeQuery_(int index, XmlNamedNativeQuery xmlNamedNativeQuery) { + OrmNamedNativeQuery query = this.buildNamedNativeQuery(xmlNamedNativeQuery); + this.addItemToList(index, query, this.namedNativeQueries, NAMED_NATIVE_QUERIES_LIST); + return query; + } + + protected void removeNamedNativeQuery_(OrmNamedNativeQuery namedNativeQuery) { + this.removeNamedNativeQuery_(this.namedNativeQueries.indexOf(namedNativeQuery)); + } + + /** + * named native query container adapter + */ + protected class NamedNativeQueryContainerAdapter + implements ContextContainerTools.Adapter<OrmNamedNativeQuery, XmlNamedNativeQuery> + { + public Iterable<OrmNamedNativeQuery> getContextElements() { + return GenericOrmQueryContainer.this.getNamedNativeQueries(); + } + public Iterable<XmlNamedNativeQuery> getResourceElements() { + return GenericOrmQueryContainer.this.getXmlNamedNativeQueries(); + } + public XmlNamedNativeQuery getResourceElement(OrmNamedNativeQuery contextElement) { + return contextElement.getXmlQuery(); + } + public void moveContextElement(int index, OrmNamedNativeQuery element) { + GenericOrmQueryContainer.this.moveNamedNativeQuery_(index, element); + } + public void addContextElement(int index, XmlNamedNativeQuery resourceElement) { + GenericOrmQueryContainer.this.addNamedNativeQuery_(index, resourceElement); + } + public void removeContextElement(OrmNamedNativeQuery element) { + GenericOrmQueryContainer.this.removeNamedNativeQuery_(element); + } + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateQueries(messages); + } + + protected void validateQueries(List<IMessage> messages) { + for (OrmQuery localQuery : this.getQueries()) { + String name = localQuery.getName(); + if (StringTools.stringIsEmpty(name)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_NAME_UNDEFINED, + new String[] {}, + localQuery, + localQuery.getNameTextRange() + ) + ); + } else { + List<String> reportedNames = new ArrayList<String>(); + for (Iterator<Query> globalQueries = this.getPersistenceUnit().queries(); globalQueries.hasNext(); ) { + Query globalQuery = globalQueries.next(); + if (localQuery.duplicates(globalQuery) && !reportedNames.contains(name)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_DUPLICATE_NAME, + new String[] {name}, + localQuery, + localQuery.getNameTextRange()) + ); + reportedNames.add(name); + } + } + } + String query = localQuery.getQuery(); + if (StringTools.stringIsEmpty(query)){ + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.QUERY_STATEMENT_UNDEFINED, + new String[] {name}, + localQuery, + localQuery.getNameTextRange() + ) + ); + } + } + } + + /** + * Return all the queries, named and named native. + */ + @SuppressWarnings("unchecked") + protected Iterable<OrmQuery> getQueries() { + return new CompositeIterable<OrmQuery>( + this.getNamedQueries(), + this.getNamedNativeQueries() + ); + } + + public TextRange getValidationTextRange() { + return this.xmlQueryContainer.getValidationTextRange(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryHint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryHint.java new file mode 100644 index 0000000000..36774ef58d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryHint.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.orm.OrmQuery; +import org.eclipse.jpt.jpa.core.context.orm.OrmQueryHint; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.orm.XmlQueryHint; + +/** + * <code>orm.xml</code> query hint + */ +public class GenericOrmQueryHint + extends AbstractOrmXmlContextNode + implements OrmQueryHint +{ + protected final XmlQueryHint xmlQueryHint; + + protected String name; + protected String value; + + + public GenericOrmQueryHint(OrmQuery parent, XmlQueryHint xmlQueryHint) { + super(parent); + this.xmlQueryHint = xmlQueryHint; + this.name = xmlQueryHint.getName(); + this.value = xmlQueryHint.getValue(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setName_(this.xmlQueryHint.getName()); + this.setValue_(this.xmlQueryHint.getValue()); + } + + + // ********** name ********** + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.setName_(name); + this.xmlQueryHint.setName(name); + } + + protected void setName_(String name) { + String old = this.name; + this.name = name; + this.firePropertyChanged(NAME_PROPERTY, old, name); + } + + + // ********** value ********** + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.setValue_(value); + this.xmlQueryHint.setValue(value); + } + + protected void setValue_(String value) { + String old = this.value; + this.value = value; + this.firePropertyChanged(VALUE_PROPERTY, old, value); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.xmlQueryHint.getValidationTextRange(); + } + + + // ********** miscelleneous ********** + + public XmlQueryHint getXmlQueryHint() { + return this.xmlQueryHint; + } + + @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/jpa1/context/orm/GenericOrmReferenceTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java new file mode 100644 index 0000000000..f6a5bc41c6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmReferenceTable.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +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.LiveCloneIterable; +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.ReadOnlyReferenceTable; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmReferenceTable; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.MappingTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmTable; +import org.eclipse.jpt.jpa.core.resource.orm.AbstractXmlReferenceTable; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlJoinColumn; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>orm.xml</code> join table or collection table + */ +public abstract class GenericOrmReferenceTable<X extends AbstractXmlReferenceTable> + extends AbstractOrmTable<X> + implements OrmReferenceTable +{ + protected final Vector<OrmJoinColumn> specifiedJoinColumns = new Vector<OrmJoinColumn>(); + protected final SpecifiedJoinColumnContainerAdapter specifiedJoinColumnContainerAdapter = new SpecifiedJoinColumnContainerAdapter(); + protected final OrmJoinColumn.Owner joinColumnOwner; + + protected OrmJoinColumn defaultJoinColumn; + + + protected GenericOrmReferenceTable(XmlContextNode parent, Owner owner) { + super(parent, owner); + 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<OrmJoinColumn> joinColumns() { + return this.getJoinColumns().iterator(); + } + + protected ListIterable<OrmJoinColumn> getJoinColumns() { + return this.hasSpecifiedJoinColumns() ? this.getSpecifiedJoinColumns() : this.getDefaultJoinColumns(); + } + + public int joinColumnsSize() { + return this.hasSpecifiedJoinColumns() ? this.specifiedJoinColumnsSize() : this.getDefaultJoinColumnsSize(); + } + + public void convertDefaultToSpecifiedJoinColumn() { + MappingTools.convertReferenceTableDefaultToSpecifiedJoinColumn(this); + } + + + // ********** specified join columns ********** + + public ListIterator<OrmJoinColumn> specifiedJoinColumns() { + return this.getSpecifiedJoinColumns().iterator(); + } + + protected ListIterable<OrmJoinColumn> getSpecifiedJoinColumns() { + return new LiveCloneListIterable<OrmJoinColumn>(this.specifiedJoinColumns); + } + + public int specifiedJoinColumnsSize() { + return this.specifiedJoinColumns.size(); + } + + public boolean hasSpecifiedJoinColumns() { + return this.specifiedJoinColumns.size() != 0; + } + + public OrmJoinColumn getSpecifiedJoinColumn(int index) { + return this.specifiedJoinColumns.get(index); + } + + public OrmJoinColumn addSpecifiedJoinColumn() { + return this.addSpecifiedJoinColumn(this.specifiedJoinColumns.size()); + } + + public OrmJoinColumn addSpecifiedJoinColumn(int index) { + X xmlTable = this.getXmlTableForUpdate(); + XmlJoinColumn xmlJoinColumn = this.buildXmlJoinColumn(); + OrmJoinColumn joinColumn = this.addSpecifiedJoinColumn_(index, xmlJoinColumn); + xmlTable.getJoinColumns().add(index, xmlJoinColumn); + return joinColumn; + } + + protected XmlJoinColumn buildXmlJoinColumn() { + return OrmFactory.eINSTANCE.createXmlJoinColumn(); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + this.removeSpecifiedJoinColumn(this.specifiedJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedJoinColumn(int index) { + this.removeSpecifiedJoinColumn_(index); + this.getXmlTable().getJoinColumns().remove(index); + this.removeXmlTableIfUnset(); + } + + protected void removeSpecifiedJoinColumn_(int index) { + this.removeItemFromList(index, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + this.getXmlTable().getJoinColumns().move(targetIndex, sourceIndex); + } + + protected void initializeSpecifiedJoinColumns() { + for (XmlJoinColumn xmlJoinColumn : this.getXmlJoinColumns()) { + this.specifiedJoinColumns.add(this.buildJoinColumn(xmlJoinColumn)); + } + } + + protected void syncSpecifiedJoinColumns() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedJoinColumnContainerAdapter); + } + + protected Iterable<XmlJoinColumn> getXmlJoinColumns() { + X xmlTable = this.getXmlTable(); + return (xmlTable == null) ? + EmptyIterable.<XmlJoinColumn>instance() : + // clone to reduce chance of concurrency problems + new LiveCloneIterable<XmlJoinColumn>(xmlTable.getJoinColumns()); + } + + protected void moveSpecifiedJoinColumn_(int index, OrmJoinColumn joinColumn) { + this.moveItemInList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + } + + protected OrmJoinColumn addSpecifiedJoinColumn_(int index, XmlJoinColumn xmlJoinColumn) { + OrmJoinColumn joinColumn = this.buildJoinColumn(xmlJoinColumn); + this.addItemToList(index, joinColumn, this.specifiedJoinColumns, SPECIFIED_JOIN_COLUMNS_LIST); + return joinColumn; + } + + protected void removeSpecifiedJoinColumn_(OrmJoinColumn joinColumn) { + this.removeSpecifiedJoinColumn_(this.specifiedJoinColumns.indexOf(joinColumn)); + } + + /** + * specified join column container adapter + */ + protected class SpecifiedJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<OrmJoinColumn, XmlJoinColumn> + { + public Iterable<OrmJoinColumn> getContextElements() { + return GenericOrmReferenceTable.this.getSpecifiedJoinColumns(); + } + public Iterable<XmlJoinColumn> getResourceElements() { + return GenericOrmReferenceTable.this.getXmlJoinColumns(); + } + public XmlJoinColumn getResourceElement(OrmJoinColumn contextElement) { + return contextElement.getXmlColumn(); + } + public void moveContextElement(int index, OrmJoinColumn element) { + GenericOrmReferenceTable.this.moveSpecifiedJoinColumn_(index, element); + } + public void addContextElement(int index, XmlJoinColumn resourceElement) { + GenericOrmReferenceTable.this.addSpecifiedJoinColumn_(index, resourceElement); + } + public void removeContextElement(OrmJoinColumn element) { + GenericOrmReferenceTable.this.removeSpecifiedJoinColumn_(element); + } + } + + protected abstract OrmJoinColumn.Owner buildJoinColumnOwner(); + + + // ********** default join column ********** + + public OrmJoinColumn getDefaultJoinColumn() { + return this.defaultJoinColumn; + } + + protected void setDefaultJoinColumn(OrmJoinColumn joinColumn) { + OrmJoinColumn old = this.defaultJoinColumn; + this.defaultJoinColumn = joinColumn; + this.firePropertyChanged(DEFAULT_JOIN_COLUMN_PROPERTY, old, joinColumn); + } + + protected ListIterable<OrmJoinColumn> getDefaultJoinColumns() { + return (this.defaultJoinColumn != null) ? + new SingleElementListIterable<OrmJoinColumn>(this.defaultJoinColumn) : + EmptyListIterable.<OrmJoinColumn>instance(); + } + + protected int getDefaultJoinColumnsSize() { + return (this.defaultJoinColumn == null) ? 0 : 1; + } + + protected void updateDefaultJoinColumn() { + if (this.buildsDefaultJoinColumn()) { + if (this.defaultJoinColumn == null) { + this.setDefaultJoinColumn(this.buildJoinColumn(null)); + } else { + this.defaultJoinColumn.update(); + } + } else { + this.setDefaultJoinColumn(null); + } + } + + protected boolean buildsDefaultJoinColumn() { + return ! this.hasSpecifiedJoinColumns(); + } + + + // ********** misc ********** + + protected void initializeFrom(ReadOnlyReferenceTable oldTable) { + super.initializeFrom(oldTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(oldTable.specifiedJoinColumns())) { + this.addSpecifiedJoinColumn().initializeFrom(joinColumn); + } + } + + protected void initializeFromVirtual(ReadOnlyReferenceTable virtualTable) { + super.initializeFromVirtual(virtualTable); + for (ReadOnlyJoinColumn joinColumn : CollectionTools.iterable(virtualTable.joinColumns())) { + this.addSpecifiedJoinColumn().initializeFromVirtual(joinColumn); + } + } + + protected OrmJoinColumn buildJoinColumn(XmlJoinColumn xmlJoinColumn) { + return this.getContextNodeFactory().buildOrmJoinColumn(this, this.joinColumnOwner, xmlJoinColumn); + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + boolean continueValidating = this.buildTableValidator().validate(messages, reporter); + + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + this.validateJoinColumns(messages, reporter); + } + } + + protected void validateJoinColumns(List<IMessage> messages, IReporter reporter) { + this.validateJoinColumns(this.getJoinColumns(), messages, reporter); + } + + protected void validateJoinColumns(Iterable<OrmJoinColumn> joinColumns, List<IMessage> messages, IReporter reporter) { + for (OrmJoinColumn joinColumn : joinColumns) { + joinColumn.validate(messages, reporter); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java new file mode 100644 index 0000000000..39971d0abb --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSecondaryTable.java @@ -0,0 +1,418 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; +import org.eclipse.jpt.common.core.utility.TextRange; +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.LiveCloneIterable; +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.BaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.NamedColumn; +import org.eclipse.jpt.jpa.core.context.PrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlyPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.ReadOnlySecondaryTable; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmEntity; +import org.eclipse.jpt.jpa.core.context.orm.OrmPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmSecondaryTable; +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.context.orm.AbstractOrmTable; +import org.eclipse.jpt.jpa.core.internal.jpa1.context.SecondaryTablePrimaryKeyJoinColumnValidator; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.resource.orm.XmlSecondaryTable; +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> secondary table + */ +public class GenericOrmSecondaryTable + extends AbstractOrmTable<XmlSecondaryTable> + implements OrmSecondaryTable +{ + /** @see AbstractOrmTable#AbstractOrmTable(org.eclipse.jpt.jpa.core.context.XmlContextNode, org.eclipse.jpt.jpa.core.context.Table.Owner, org.eclipse.jpt.jpa.core.resource.orm.AbstractXmlTable) */ + protected /* final */ XmlSecondaryTable xmlSecondaryTable; + + protected final Vector<OrmPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns = new Vector<OrmPrimaryKeyJoinColumn>(); + protected final SpecifiedPrimaryKeyJoinColumnContainerAdapter specifiedPrimaryKeyJoinColumnContainerAdapter = new SpecifiedPrimaryKeyJoinColumnContainerAdapter(); + protected final OrmBaseJoinColumn.Owner primaryKeyJoinColumnOwner; + + protected OrmPrimaryKeyJoinColumn defaultPrimaryKeyJoinColumn; + + + public GenericOrmSecondaryTable(OrmEntity parent, Owner owner, XmlSecondaryTable xmlSecondaryTable) { + super(parent, owner, xmlSecondaryTable); + this.primaryKeyJoinColumnOwner = this.buildPrimaryKeyJoinColumnOwner(); + this.initializeSpecifiedPrimaryKeyJoinColumns(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncSpecifiedPrimaryKeyJoinColumns(); + if (this.defaultPrimaryKeyJoinColumn != null) { + this.defaultPrimaryKeyJoinColumn.synchronizeWithResourceModel(); + } + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getSpecifiedPrimaryKeyJoinColumns()); + this.updateDefaultPrimaryKeyJoinColumn(); + } + + + // ********** XML table ********** + + @Override + public XmlSecondaryTable getXmlTable() { + return this.xmlSecondaryTable; + } + + /** + * @see AbstractOrmTable + */ + @Override + protected void setXmlTable(XmlSecondaryTable xmlTable) { + this.xmlSecondaryTable = xmlTable; + } + + /** + * secondary tables are part of a collection; + * the 'secondary-table' element will be removed from/added + * when the XML secondary table is removed/added to + * the XML entity's collection + */ + @Override + protected XmlSecondaryTable buildXmlTable() { + throw new IllegalStateException("XML secondary table is missing"); //$NON-NLS-1$ + } + + /** + * @see #buildXmlTable() + */ + @Override + protected void removeXmlTable() { + // do nothing + } + + + // ********** primary key join columns ********** + + public ListIterator<OrmPrimaryKeyJoinColumn> primaryKeyJoinColumns() { + return this.getPrimaryKeyJoinColumns().iterator(); + } + + protected ListIterable<OrmPrimaryKeyJoinColumn> getPrimaryKeyJoinColumns() { + return this.hasSpecifiedPrimaryKeyJoinColumns() ? this.getSpecifiedPrimaryKeyJoinColumns() : this.getDefaultPrimaryKeyJoinColumns(); + } + + public int primaryKeyJoinColumnsSize() { + return this.hasSpecifiedPrimaryKeyJoinColumns() ? this.specifiedPrimaryKeyJoinColumnsSize() : this.getDefaultPrimaryKeyJoinColumnsSize(); + } + + + // ********** specified primary key join columns ********** + + public ListIterator<OrmPrimaryKeyJoinColumn> specifiedPrimaryKeyJoinColumns() { + return this.getSpecifiedPrimaryKeyJoinColumns().iterator(); + } + + public ListIterable<OrmPrimaryKeyJoinColumn> getSpecifiedPrimaryKeyJoinColumns() { + return new LiveCloneListIterable<OrmPrimaryKeyJoinColumn>(this.specifiedPrimaryKeyJoinColumns); + } + + public int specifiedPrimaryKeyJoinColumnsSize() { + return this.specifiedPrimaryKeyJoinColumns.size(); + } + + protected boolean hasSpecifiedPrimaryKeyJoinColumns() { + return this.specifiedPrimaryKeyJoinColumns.size() != 0; + } + + public OrmPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn() { + return this.addSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.size()); + } + + public OrmPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn(int index) { + XmlPrimaryKeyJoinColumn xmlJoinColumn = this.buildXmlPrimaryKeyJoinColumn(); + OrmPrimaryKeyJoinColumn joinColumn = this.addSpecifiedPrimaryKeyJoinColumn_(index, xmlJoinColumn); + this.xmlSecondaryTable.getPrimaryKeyJoinColumns().add(index, xmlJoinColumn); + return joinColumn; + } + + protected XmlPrimaryKeyJoinColumn buildXmlPrimaryKeyJoinColumn() { + return OrmFactory.eINSTANCE.createXmlPrimaryKeyJoinColumn(); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(PrimaryKeyJoinColumn joinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn(this.specifiedPrimaryKeyJoinColumns.indexOf(joinColumn)); + } + + public void removeSpecifiedPrimaryKeyJoinColumn(int index) { + this.removeSpecifiedPrimaryKeyJoinColumn_(index); + this.xmlSecondaryTable.getPrimaryKeyJoinColumns().remove(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.moveItemInList(targetIndex, sourceIndex, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + this.xmlSecondaryTable.getPrimaryKeyJoinColumns().move(targetIndex, sourceIndex); + } + + protected void initializeSpecifiedPrimaryKeyJoinColumns() { + for (XmlPrimaryKeyJoinColumn xmlJoinColumn : this.getXmlPrimaryKeyJoinColumns()) { + this.specifiedPrimaryKeyJoinColumns.add(this.buildPrimaryKeyJoinColumn(xmlJoinColumn)); + } + } + + protected void syncSpecifiedPrimaryKeyJoinColumns() { + ContextContainerTools.synchronizeWithResourceModel(this.specifiedPrimaryKeyJoinColumnContainerAdapter); + } + + protected Iterable<XmlPrimaryKeyJoinColumn> getXmlPrimaryKeyJoinColumns() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlPrimaryKeyJoinColumn>(this.xmlSecondaryTable.getPrimaryKeyJoinColumns()); + } + + protected void moveSpecifiedPrimaryKeyJoinColumn_(int index, OrmPrimaryKeyJoinColumn joinColumn) { + this.moveItemInList(index, joinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + } + + protected OrmPrimaryKeyJoinColumn addSpecifiedPrimaryKeyJoinColumn_(int index, XmlPrimaryKeyJoinColumn xmlJoinColumn) { + OrmPrimaryKeyJoinColumn joinColumn = this.buildPrimaryKeyJoinColumn(xmlJoinColumn); + this.addItemToList(index, joinColumn, this.specifiedPrimaryKeyJoinColumns, SPECIFIED_PRIMARY_KEY_JOIN_COLUMNS_LIST); + return joinColumn; + } + + protected void removeSpecifiedPrimaryKeyJoinColumn_(OrmPrimaryKeyJoinColumn joinColumn) { + this.removeSpecifiedPrimaryKeyJoinColumn_(this.specifiedPrimaryKeyJoinColumns.indexOf(joinColumn)); + } + + /** + * specified primary key join column container adapter + */ + protected class SpecifiedPrimaryKeyJoinColumnContainerAdapter + implements ContextContainerTools.Adapter<OrmPrimaryKeyJoinColumn, XmlPrimaryKeyJoinColumn> + { + public Iterable<OrmPrimaryKeyJoinColumn> getContextElements() { + return GenericOrmSecondaryTable.this.getSpecifiedPrimaryKeyJoinColumns(); + } + public Iterable<XmlPrimaryKeyJoinColumn> getResourceElements() { + return GenericOrmSecondaryTable.this.getXmlPrimaryKeyJoinColumns(); + } + public XmlPrimaryKeyJoinColumn getResourceElement(OrmPrimaryKeyJoinColumn contextElement) { + return contextElement.getXmlColumn(); + } + public void moveContextElement(int index, OrmPrimaryKeyJoinColumn element) { + GenericOrmSecondaryTable.this.moveSpecifiedPrimaryKeyJoinColumn_(index, element); + } + public void addContextElement(int index, XmlPrimaryKeyJoinColumn resourceElement) { + GenericOrmSecondaryTable.this.addSpecifiedPrimaryKeyJoinColumn_(index, resourceElement); + } + public void removeContextElement(OrmPrimaryKeyJoinColumn element) { + GenericOrmSecondaryTable.this.removeSpecifiedPrimaryKeyJoinColumn_(element); + } + } + + protected OrmBaseJoinColumn.Owner buildPrimaryKeyJoinColumnOwner() { + return new PrimaryKeyJoinColumnOwner(); + } + + + // ********** default primary key join column ********** + + public OrmPrimaryKeyJoinColumn getDefaultPrimaryKeyJoinColumn() { + return this.defaultPrimaryKeyJoinColumn; + } + + protected void setDefaultPrimaryKeyJoinColumn(OrmPrimaryKeyJoinColumn joinColumn) { + OrmPrimaryKeyJoinColumn old = this.defaultPrimaryKeyJoinColumn; + this.defaultPrimaryKeyJoinColumn = joinColumn; + this.firePropertyChanged(DEFAULT_PRIMARY_KEY_JOIN_COLUMN, old, joinColumn); + } + + protected ListIterable<OrmPrimaryKeyJoinColumn> getDefaultPrimaryKeyJoinColumns() { + return (this.defaultPrimaryKeyJoinColumn != null) ? + new SingleElementListIterable<OrmPrimaryKeyJoinColumn>(this.defaultPrimaryKeyJoinColumn) : + EmptyListIterable.<OrmPrimaryKeyJoinColumn>instance(); + } + + protected int getDefaultPrimaryKeyJoinColumnsSize() { + return (this.defaultPrimaryKeyJoinColumn == null) ? 0 : 1; + } + + protected void updateDefaultPrimaryKeyJoinColumn() { + if (this.buildsDefaultPrimaryKeyJoinColumn()) { + if (this.defaultPrimaryKeyJoinColumn == null) { + this.setDefaultPrimaryKeyJoinColumn(this.buildPrimaryKeyJoinColumn(null)); + } else { + this.defaultPrimaryKeyJoinColumn.update(); + } + } else { + this.setDefaultPrimaryKeyJoinColumn(null); + } + } + + protected boolean buildsDefaultPrimaryKeyJoinColumn() { + return ! this.hasSpecifiedPrimaryKeyJoinColumns(); + } + + + // ********** misc ********** + + @Override + public OrmEntity getParent() { + return (OrmEntity) super.getParent(); + } + + protected OrmEntity getEntity() { + return this.getParent(); + } + + public boolean isVirtual() { + return false; + } + + public void initializeFrom(ReadOnlySecondaryTable oldSecondaryTable) { + super.initializeFrom(oldSecondaryTable); + for (ReadOnlyPrimaryKeyJoinColumn pkJoinColumn : CollectionTools.iterable(oldSecondaryTable.specifiedPrimaryKeyJoinColumns())) { + this.addSpecifiedPrimaryKeyJoinColumn().initializeFrom(pkJoinColumn); + } + } + + protected OrmPrimaryKeyJoinColumn buildPrimaryKeyJoinColumn(XmlPrimaryKeyJoinColumn xmlJoinColumn) { + return this.getContextNodeFactory().buildOrmPrimaryKeyJoinColumn(this, this.primaryKeyJoinColumnOwner, xmlJoinColumn); + } + + + // ********** defaults ********** + + /** + * a secondary table doesn't have a default name + */ + @Override + protected String buildDefaultName() { + return null; + } + + @Override + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** validation ********** + + public boolean validatesAgainstDatabase() { + return this.connectionProfileIsActive(); + } + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + boolean continueValidating = this.buildTableValidator().validate(messages, reporter); + + //join column validation will handle the check for whether to validate against the database + //some validation messages are not database specific. If the database validation for the + //table fails we will stop there and not validate the join columns at all + if (continueValidating) { + for (OrmPrimaryKeyJoinColumn pkJoinColumn : this.getPrimaryKeyJoinColumns()) { + pkJoinColumn.validate(messages, reporter); + } + } + } + + + // ********** primary key join column owner adapter ********** + + protected class PrimaryKeyJoinColumnOwner + implements OrmBaseJoinColumn.Owner + { + protected OrmEntity getEntity() { + return GenericOrmSecondaryTable.this.getEntity(); + } + + public TypeMapping getTypeMapping() { + return this.getEntity(); + } + + public String getDefaultTableName() { + return GenericOrmSecondaryTable.this.getName(); + } + + public String getDefaultColumnName() { + if (this.joinColumnsSize() != 1) { + return null; + } + Entity parentEntity = this.getEntity().getParentEntity(); + return (parentEntity != null) ? + parentEntity.getPrimaryKeyColumnName() : + this.getEntity().getPrimaryKeyColumnName(); + } + + public Table resolveDbTable(String tableName) { + return GenericOrmSecondaryTable.this.getDbTable(); + } + + public int joinColumnsSize() { + return GenericOrmSecondaryTable.this.primaryKeyJoinColumnsSize(); + } + + public boolean joinColumnIsDefault(ReadOnlyBaseJoinColumn joinColumn) { + return GenericOrmSecondaryTable.this.defaultPrimaryKeyJoinColumn == joinColumn; + } + + public Table getReferencedColumnDbTable() { + return this.getTypeMapping().getPrimaryDbTable(); + } + + public TextRange getValidationTextRange() { + return GenericOrmSecondaryTable.this.getValidationTextRange(); + } + + protected boolean isSecondaryTableVirtual() { + return GenericOrmSecondaryTable.this.isVirtual(); + } + + protected String getSecondaryTableName() { + return GenericOrmSecondaryTable.this.getName(); + } + + public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { + return new SecondaryTablePrimaryKeyJoinColumnValidator(GenericOrmSecondaryTable.this, (BaseJoinColumn) column, this, (BaseJoinColumnTextRangeResolver) textRangeResolver); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java new file mode 100644 index 0000000000..5e56c71cc4 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmSequenceGenerator.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmSequenceGenerator; +import org.eclipse.jpt.jpa.core.resource.orm.XmlSequenceGenerator; + +/** + * <code>orm.xml</code> sequence generator + */ +public class GenericOrmSequenceGenerator + extends AbstractOrmSequenceGenerator +{ + public GenericOrmSequenceGenerator(XmlContextNode parent, XmlSequenceGenerator xmlSequenceGenerator) { + super(parent, xmlSequenceGenerator); + } + + // ********** database stuff ********** + + /** + * The JPA 1.0 spec does not allow a sequence to specify a catalog. + */ + @Override + protected String getCatalog() { + return this.getContextDefaultCatalog(); + } + + /** + * The JPA 1.0 spec does not allow a sequence to specify a schema. + */ + @Override + protected String getSchema() { + return this.getContextDefaultSchema(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTable.java new file mode 100644 index 0000000000..0832952ada --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTable.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmEntity; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmTable; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEntity; +import org.eclipse.jpt.jpa.core.resource.orm.XmlTable; + +/** + * <code>orm.xml</code> table + */ +public class GenericOrmTable + extends AbstractOrmTable<XmlTable> +{ + public GenericOrmTable(OrmEntity parent, Owner owner) { + super(parent, owner); + } + + + // ********** XML table ********** + + @Override + protected XmlTable getXmlTable() { + return this.getXmlEntity().getTable(); + } + + @Override + protected XmlTable buildXmlTable() { + XmlTable xmlTable = OrmFactory.eINSTANCE.createXmlTable(); + this.getXmlEntity().setTable(xmlTable); + return xmlTable; + } + + @Override + protected void removeXmlTable() { + this.getXmlEntity().setTable(null); + } + + protected XmlEntity getXmlEntity() { + return this.getEntity().getXmlTypeMapping(); + } + + + // ********** defaults ********** + + @Override + protected String buildDefaultName() { + return this.getEntity().getDefaultTableName(); + } + + @Override + protected String buildDefaultSchema() { + return this.getEntity().getDefaultSchema(); + } + + @Override + protected String buildDefaultCatalog() { + return this.getEntity().getDefaultCatalog(); + } + + + // ********** validation ********** + + public boolean validatesAgainstDatabase() { + return this.connectionProfileIsActive(); + } + + + // ********** misc ********** + + @Override + public OrmEntity getParent() { + return (OrmEntity) super.getParent(); + } + + protected OrmEntity getEntity() { + return this.getParent(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java new file mode 100644 index 0000000000..9805b186f0 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTableGenerator.java @@ -0,0 +1,440 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.Iterator; +import java.util.Vector; + +import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator; +import org.eclipse.jpt.jpa.core.context.UniqueConstraint; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmTableGenerator; +import org.eclipse.jpt.jpa.core.context.orm.OrmUniqueConstraint; +import org.eclipse.jpt.jpa.core.internal.context.ContextContainerTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmGenerator; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; +import org.eclipse.jpt.jpa.core.resource.orm.XmlTableGenerator; +import org.eclipse.jpt.jpa.core.resource.orm.XmlUniqueConstraint; +import org.eclipse.jpt.jpa.db.Schema; +import org.eclipse.jpt.jpa.db.Table; + +/** + * <code>orm.xml</code> table generator + */ +public class GenericOrmTableGenerator + extends AbstractOrmGenerator<XmlTableGenerator> + implements OrmTableGenerator, UniqueConstraint.Owner +{ + protected String specifiedTable; + protected String defaultTable; + + protected String specifiedSchema; + protected String defaultSchema; + + protected String specifiedCatalog; + protected String defaultCatalog; + + protected String specifiedPkColumnName; + protected String defaultPkColumnName; + + protected String specifiedValueColumnName; + protected String defaultValueColumnName; + + protected String specifiedPkColumnValue; + protected String defaultPkColumnValue; + + protected final Vector<OrmUniqueConstraint> uniqueConstraints = new Vector<OrmUniqueConstraint>(); + protected final UniqueConstraintContainerAdapter uniqueConstraintContainerAdapter = new UniqueConstraintContainerAdapter(); + + + // ********** constructor ********** + + public GenericOrmTableGenerator(XmlContextNode parent, XmlTableGenerator xmlTableGenerator) { + super(parent, xmlTableGenerator); + this.specifiedTable = xmlTableGenerator.getTable(); + this.specifiedSchema = xmlTableGenerator.getSchema(); + this.specifiedCatalog = xmlTableGenerator.getCatalog(); + this.specifiedPkColumnName = xmlTableGenerator.getPkColumnName(); + this.specifiedValueColumnName = xmlTableGenerator.getValueColumnName(); + this.specifiedPkColumnValue = xmlTableGenerator.getPkColumnValue(); + this.initializeUniqueContraints(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setSpecifiedTable_(this.xmlGenerator.getTable()); + this.setSpecifiedSchema_(this.xmlGenerator.getSchema()); + this.setSpecifiedCatalog_(this.xmlGenerator.getCatalog()); + this.setSpecifiedPkColumnName_(this.xmlGenerator.getPkColumnName()); + this.setSpecifiedValueColumnName_(this.xmlGenerator.getValueColumnName()); + this.setSpecifiedPkColumnValue_(this.xmlGenerator.getPkColumnValue()); + this.syncUniqueConstraints(); + } + + @Override + public void update() { + super.update(); + this.setDefaultTable(this.buildDefaultTable()); + this.setDefaultSchema(this.buildDefaultSchema()); + this.setDefaultCatalog(this.buildDefaultCatalog()); + this.setDefaultPkColumnName(this.buildDefaultPkColumnName()); + this.setDefaultValueColumnName(this.buildDefaultValueColumnName()); + this.setDefaultPkColumnValue(this.buildDefaultPkColumnValue()); + this.updateNodes(this.getUniqueConstraints()); + } + + + // ********** initial value ********** + + @Override + protected int buildDefaultInitialValue() { + return DEFAULT_INITIAL_VALUE; + } + + + // ********** table ********** + + public String getTable() { + return (this.specifiedTable != null) ? this.specifiedTable : this.defaultTable; + } + + public String getSpecifiedTable() { + return this.specifiedTable; + } + + public void setSpecifiedTable(String table) { + this.setSpecifiedTable_(table); + this.xmlGenerator.setTable(table); + } + + protected void setSpecifiedTable_(String table) { + String old = this.specifiedTable; + this.specifiedTable = table; + this.firePropertyChanged(SPECIFIED_TABLE_PROPERTY, old, table); + } + + public String getDefaultTable() { + return this.defaultTable; + } + + protected void setDefaultTable(String table) { + String old = this.defaultTable; + this.defaultTable = table; + this.firePropertyChanged(DEFAULT_TABLE_PROPERTY, old, table); + } + + protected String buildDefaultTable() { + return null; // TODO the default table is determined by the runtime provider... + } + + public Table getDbTable() { + Schema dbSchema = this.getDbSchema(); + return (dbSchema == null) ? null : dbSchema.getTableForIdentifier(this.getTable()); + } + + + // ********** schema ********** + + @Override + public String getSchema() { + return (this.specifiedSchema != null) ? this.specifiedSchema : this.defaultSchema; + } + + public String getSpecifiedSchema() { + return this.specifiedSchema; + } + + public void setSpecifiedSchema(String schema) { + this.setSpecifiedSchema_(schema); + this.xmlGenerator.setSchema(schema); + } + + protected void setSpecifiedSchema_(String schema) { + String old = this.specifiedSchema; + this.specifiedSchema = schema; + this.firePropertyChanged(SPECIFIED_SCHEMA_PROPERTY, old, schema); + } + + public String getDefaultSchema() { + return this.defaultSchema; + } + + protected void setDefaultSchema(String schema) { + String old = this.defaultSchema; + this.defaultSchema = schema; + this.firePropertyChanged(DEFAULT_SCHEMA_PROPERTY, old, schema); + } + + protected String buildDefaultSchema() { + return this.getContextDefaultSchema(); + } + + + // ********** catalog ********** + + @Override + public String getCatalog() { + return (this.specifiedCatalog != null) ? this.specifiedCatalog : this.defaultCatalog; + } + + public String getSpecifiedCatalog() { + return this.specifiedCatalog; + } + + public void setSpecifiedCatalog(String catalog) { + this.setSpecifiedCatalog_(catalog); + this.xmlGenerator.setCatalog(catalog); + } + + protected void setSpecifiedCatalog_(String catalog) { + String old = this.specifiedCatalog; + this.specifiedCatalog = catalog; + this.firePropertyChanged(SPECIFIED_CATALOG_PROPERTY, old, catalog); + } + + public String getDefaultCatalog() { + return this.defaultCatalog; + } + + protected void setDefaultCatalog(String catalog) { + String old = this.defaultCatalog; + this.defaultCatalog = catalog; + this.firePropertyChanged(DEFAULT_CATALOG_PROPERTY, old, catalog); + } + + protected String buildDefaultCatalog() { + return this.getContextDefaultCatalog(); + } + + + // ********** primary key column name ********** + + public String getPkColumnName() { + return (this.specifiedPkColumnName != null) ? this.specifiedPkColumnName : this.defaultPkColumnName; + } + + public String getSpecifiedPkColumnName() { + return this.specifiedPkColumnName; + } + + public void setSpecifiedPkColumnName(String name) { + this.setSpecifiedPkColumnName_(name); + this.xmlGenerator.setPkColumnName(name); + } + + protected void setSpecifiedPkColumnName_(String name) { + String old = this.specifiedPkColumnName; + this.specifiedPkColumnName = name; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultPkColumnName() { + return this.defaultPkColumnName; + } + + protected void setDefaultPkColumnName(String name) { + String old = this.defaultPkColumnName; + this.defaultPkColumnName = name; + this.firePropertyChanged(DEFAULT_PK_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultPkColumnName() { + return null; // TODO the default pk column name is determined by the runtime provider... + } + + + // ********** value column name ********** + + public String getValueColumnName() { + return (this.specifiedValueColumnName != null) ? this.specifiedValueColumnName : this.defaultValueColumnName; + } + + public String getSpecifiedValueColumnName() { + return this.specifiedValueColumnName; + } + + public void setSpecifiedValueColumnName(String name) { + this.setSpecifiedValueColumnName_(name); + this.xmlGenerator.setValueColumnName(name); + } + + protected void setSpecifiedValueColumnName_(String name) { + String old = this.specifiedValueColumnName; + this.specifiedValueColumnName = name; + this.firePropertyChanged(SPECIFIED_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + public String getDefaultValueColumnName() { + return this.defaultValueColumnName; + } + + protected void setDefaultValueColumnName(String name) { + String old = this.defaultValueColumnName; + this.defaultValueColumnName = name; + this.firePropertyChanged(DEFAULT_VALUE_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultValueColumnName() { + return null; // TODO the default value column name is determined by the runtime provider... + } + + + // ********** primary key column value ********** + + public String getPkColumnValue() { + return (this.specifiedPkColumnValue != null) ? this.specifiedPkColumnValue : this.defaultPkColumnValue; + } + + public String getSpecifiedPkColumnValue() { + return this.specifiedPkColumnValue; + } + + public void setSpecifiedPkColumnValue(String value) { + this.setSpecifiedPkColumnValue_(value); + this.xmlGenerator.setPkColumnValue(value); + } + + protected void setSpecifiedPkColumnValue_(String value) { + String old = this.specifiedPkColumnValue; + this.specifiedPkColumnValue = value; + this.firePropertyChanged(SPECIFIED_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + public String getDefaultPkColumnValue() { + return this.defaultPkColumnValue; + } + + protected void setDefaultPkColumnValue(String value) { + String old = this.defaultPkColumnValue; + this.defaultPkColumnValue = value; + this.firePropertyChanged(DEFAULT_PK_COLUMN_VALUE_PROPERTY, old, value); + } + + protected String buildDefaultPkColumnValue() { + return null; // TODO the default pk column value is determined by the runtime provider... + } + + + // ********** unique constraints ********** + + public Iterable<OrmUniqueConstraint> getUniqueConstraints() { + return new LiveCloneIterable<OrmUniqueConstraint>(this.uniqueConstraints); + } + + public int getUniqueConstraintsSize() { + return this.uniqueConstraints.size(); + } + + public OrmUniqueConstraint addUniqueConstraint() { + return this.addUniqueConstraint(this.uniqueConstraints.size()); + } + + public OrmUniqueConstraint addUniqueConstraint(int index) { + XmlUniqueConstraint xmlConstraint = this.buildXmlUniqueConstraint(); + OrmUniqueConstraint constraint = this.addUniqueConstraint_(index, xmlConstraint); + this.xmlGenerator.getUniqueConstraints().add(index, xmlConstraint); + return constraint; + } + + protected XmlUniqueConstraint buildXmlUniqueConstraint() { + return OrmFactory.eINSTANCE.createXmlUniqueConstraint(); + } + + public void removeUniqueConstraint(UniqueConstraint uniqueConstraint) { + this.removeUniqueConstraint(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + public void removeUniqueConstraint(int index) { + this.removeUniqueConstraint_(index); + this.xmlGenerator.getUniqueConstraints().remove(index); + } + + protected void removeUniqueConstraint_(int index) { + this.removeItemFromList(index, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + public void moveUniqueConstraint(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + this.xmlGenerator.getUniqueConstraints().move(targetIndex, sourceIndex); + } + + protected void initializeUniqueContraints() { + for (XmlUniqueConstraint constraint : this.getXmlUniqueConstraints()) { + this.uniqueConstraints.add(this.buildUniqueConstraint(constraint)); + } + } + + protected OrmUniqueConstraint buildUniqueConstraint(XmlUniqueConstraint resourceUniqueConstraint) { + return this.getContextNodeFactory().buildOrmUniqueConstraint(this, this, resourceUniqueConstraint); + } + + protected void syncUniqueConstraints() { + ContextContainerTools.synchronizeWithResourceModel(this.uniqueConstraintContainerAdapter); + } + + protected Iterable<XmlUniqueConstraint> getXmlUniqueConstraints() { + // clone to reduce chance of concurrency problems + return new LiveCloneIterable<XmlUniqueConstraint>(this.xmlGenerator.getUniqueConstraints()); + } + + protected void moveUniqueConstraint_(int index, OrmUniqueConstraint uniqueConstraint) { + this.moveItemInList(index, uniqueConstraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + } + + protected OrmUniqueConstraint addUniqueConstraint_(int index, XmlUniqueConstraint xmlConstraint) { + OrmUniqueConstraint constraint = this.buildUniqueConstraint(xmlConstraint); + this.addItemToList(index, constraint, this.uniqueConstraints, UNIQUE_CONSTRAINTS_LIST); + return constraint; + } + + protected void removeUniqueConstraint_(OrmUniqueConstraint uniqueConstraint) { + this.removeUniqueConstraint_(this.uniqueConstraints.indexOf(uniqueConstraint)); + } + + /** + * unique constraint container adapter + */ + protected class UniqueConstraintContainerAdapter + implements ContextContainerTools.Adapter<OrmUniqueConstraint, XmlUniqueConstraint> + { + public Iterable<OrmUniqueConstraint> getContextElements() { + return GenericOrmTableGenerator.this.getUniqueConstraints(); + } + public Iterable<XmlUniqueConstraint> getResourceElements() { + return GenericOrmTableGenerator.this.getXmlUniqueConstraints(); + } + public XmlUniqueConstraint getResourceElement(OrmUniqueConstraint contextElement) { + return contextElement.getXmlUniqueConstraint(); + } + public void moveContextElement(int index, OrmUniqueConstraint element) { + GenericOrmTableGenerator.this.moveUniqueConstraint_(index, element); + } + public void addContextElement(int index, XmlUniqueConstraint resourceElement) { + GenericOrmTableGenerator.this.addUniqueConstraint_(index, resourceElement); + } + public void removeContextElement(OrmUniqueConstraint element) { + GenericOrmTableGenerator.this.removeUniqueConstraint_(element); + } + } + + + // ********** 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(); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java new file mode 100644 index 0000000000..c95d8743e9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTemporalConverter.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.TemporalConverter; +import org.eclipse.jpt.jpa.core.context.TemporalType; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmTemporalConverter; +import org.eclipse.text.edits.ReplaceEdit; + +public class GenericOrmTemporalConverter + extends AbstractOrmConverter + implements OrmTemporalConverter +{ + protected TemporalType temporalType; + + + public GenericOrmTemporalConverter(OrmAttributeMapping parent) { + super(parent); + this.temporalType = this.buildTemporalType(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setTemporalType_(this.buildTemporalType()); + } + + + // ********** temporal type ********** + + public TemporalType getTemporalType() { + return this.temporalType; + } + + public void setTemporalType(TemporalType temporalType) { + this.setTemporalType_(temporalType); + this.setXmlTemporal(temporalType); + } + + protected void setTemporalType_(TemporalType temporalType) { + TemporalType old = this.temporalType; + this.temporalType = temporalType; + this.firePropertyChanged(TEMPORAL_TYPE_PROPERTY, old, temporalType); + } + + protected void setXmlTemporal(TemporalType temporalType) { + this.getXmlConvertibleMapping().setTemporal(TemporalType.toOrmResourceModel(temporalType)); + } + + protected TemporalType buildTemporalType() { + return TemporalType.fromOrmResourceModel(this.getXmlConvertibleMapping().getTemporal()); + } + + + // ********** misc ********** + + public Class<? extends Converter> getType() { + return TemporalConverter.class; + } + + public void initialize() { + // start with DATE(?) + this.temporalType = TemporalType.DATE; + this.setXmlTemporal(this.temporalType); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.getXmlConvertibleMapping().getTemporalTextRange(); + } + + + // ********** refactoring ********** + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return EmptyIterable.instance(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java new file mode 100644 index 0000000000..fdd0cbbe07 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmTransientMapping.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.MappingKeys; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.context.orm.OrmTransientMapping; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.XmlTransient; + +/** + * <code>orm.xml</code> transient mapping + */ +public class GenericOrmTransientMapping + extends AbstractOrmAttributeMapping<XmlTransient> + implements OrmTransientMapping +{ + public GenericOrmTransientMapping(OrmPersistentAttribute parent, XmlTransient xmlMapping) { + super(parent, xmlMapping); + } + + public String getKey() { + return MappingKeys.TRANSIENT_ATTRIBUTE_MAPPING_KEY; + } + + public int getXmlSequence() { + return 90; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmTransientMapping(this); + } + + public void addXmlAttributeMappingTo(Attributes resourceAttributes) { + resourceAttributes.getTransients().add(this.xmlAttributeMapping); + } + + public void removeXmlAttributeMappingFrom(Attributes resourceAttributes) { + resourceAttributes.getTransients().remove(this.xmlAttributeMapping); + } + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java new file mode 100644 index 0000000000..372829c881 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmUniqueConstraint.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.ReadOnlyUniqueConstraint; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmUniqueConstraint; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmReadOnlyUniqueConstraint; +import org.eclipse.jpt.jpa.core.resource.orm.XmlUniqueConstraint; + +public class GenericOrmUniqueConstraint + extends AbstractOrmReadOnlyUniqueConstraint + implements OrmUniqueConstraint +{ + protected Owner owner; + protected final XmlUniqueConstraint xmlUniqueConstraint; + + + public GenericOrmUniqueConstraint(XmlContextNode parent, Owner owner, XmlUniqueConstraint xmlUniqueConstraint) { + super(parent); + this.owner = owner; + this.xmlUniqueConstraint = xmlUniqueConstraint; + this.initializeColumnNames(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncColumnNames(); + } + + + // ********** column names ********** + + public void addColumnName(String columnName) { + this.addColumnName(this.columnNames.size(), columnName); + } + + public void addColumnName(int index, String columnName) { + this.addItemToList(index, columnName, this.columnNames, COLUMN_NAMES_LIST); + this.xmlUniqueConstraint.getColumnNames().add(index, columnName); + } + + public void removeColumnName(String columnName) { + this.removeColumnName(this.columnNames.indexOf(columnName)); + } + + public void removeColumnName(int index) { + this.removeItemFromList(index, this.columnNames, COLUMN_NAMES_LIST); + this.xmlUniqueConstraint.getColumnNames().remove(index); + } + + public void moveColumnName(int targetIndex, int sourceIndex) { + this.moveItemInList(targetIndex, sourceIndex, this.columnNames, COLUMN_NAMES_LIST); + this.xmlUniqueConstraint.getColumnNames().move(targetIndex, sourceIndex); + } + + protected void initializeColumnNames() { + for (String xmlColumnName : this.xmlUniqueConstraint.getColumnNames()) { + this.columnNames.add(xmlColumnName); + } + } + + @Override + protected Iterable<String> getResourceColumnNames() { + return this.xmlUniqueConstraint.getColumnNames(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.xmlUniqueConstraint.getValidationTextRange(); + } + + + // ********** misc ********** + + public XmlUniqueConstraint getXmlUniqueConstraint() { + return this.xmlUniqueConstraint; + } + + public void initializeFrom(ReadOnlyUniqueConstraint oldUniqueConstraint) { + for (String columnName : oldUniqueConstraint.getColumnNames()) { + this.addColumnName(columnName); + } + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java new file mode 100644 index 0000000000..5cd6602686 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVersionMapping.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmVersionMapping; +import org.eclipse.jpt.jpa.core.resource.orm.XmlVersion; + + +public class GenericOrmVersionMapping + extends AbstractOrmVersionMapping<XmlVersion> +{ + public GenericOrmVersionMapping(OrmPersistentAttribute parent, XmlVersion xmlMapping) { + super(parent, xmlMapping); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAssociationOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAssociationOverride.java new file mode 100644 index 0000000000..aee0a4591d --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAssociationOverride.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.Relationship; +import org.eclipse.jpt.jpa.core.context.RelationshipMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAssociationOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualOverrideRelationship; + +/** + * Virtual <code>orm.xml</code> association override + */ +public class GenericOrmVirtualAssociationOverride + extends AbstractOrmVirtualOverride<OrmAssociationOverrideContainer> + implements OrmVirtualAssociationOverride +{ + protected final OrmVirtualOverrideRelationship relationship; + + + public GenericOrmVirtualAssociationOverride(OrmAssociationOverrideContainer parent, String name) { + super(parent, name); + this.relationship = this.buildRelationship(); + } + + @Override + public void update() { + super.update(); + this.relationship.update(); + } + + @Override + public OrmAssociationOverride convertToSpecified() { + return (OrmAssociationOverride) super.convertToSpecified(); + } + + public RelationshipMapping getMapping() { + return this.getContainer().getRelationshipMapping(this.name); + } + + + // ********** relationship ********** + + public OrmVirtualOverrideRelationship getRelationship() { + return this.relationship; + } + + /** + * The relationship should be available (since its presence precipitated the + * creation of the virtual override). + */ + protected OrmVirtualOverrideRelationship buildRelationship() { + return this.getContextNodeFactory().buildOrmVirtualOverrideRelationship(this); + } + + public Relationship resolveOverriddenRelationship() { + return this.getContainer().resolveOverriddenRelationship(this.name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAttributeOverride.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAttributeOverride.java new file mode 100644 index 0000000000..d1327dba88 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualAttributeOverride.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.ReadOnlyColumn; +import org.eclipse.jpt.jpa.core.context.TypeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeOverrideContainer; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualAttributeOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualColumn; + +/** + * Virtual <code>orm.xml</code> attribute override + */ +public class GenericOrmVirtualAttributeOverride + extends AbstractOrmVirtualOverride<OrmAttributeOverrideContainer> + implements OrmVirtualAttributeOverride, OrmVirtualColumn.Owner +{ + protected final OrmVirtualColumn column; + + + public GenericOrmVirtualAttributeOverride(OrmAttributeOverrideContainer parent, String name) { + super(parent, name); + this.column = this.buildColumn(); + } + + @Override + public void update() { + super.update(); + this.column.update(); + } + + @Override + public OrmAttributeOverride convertToSpecified() { + return (OrmAttributeOverride) super.convertToSpecified(); + } + + + // ********** column ********** + + public OrmVirtualColumn getColumn() { + return this.column; + } + + /** + * The original column should be available (since the presence of its + * attribute is what precipitated the creation of the virtual override). + */ + protected OrmVirtualColumn buildColumn() { + return this.getContextNodeFactory().buildOrmVirtualColumn(this, this); + } + + + // ********** column owner implementation ********** + + public TypeMapping getTypeMapping() { + return this.getContainer().getTypeMapping(); + } + + public String getDefaultTableName() { + String overriddenColumnTable = this.getOverriddenColumnTable(); + return (overriddenColumnTable != null) ? overriddenColumnTable : this.getContainer().getDefaultTableName(); + } + + protected String getOverriddenColumnTable() { + ReadOnlyColumn overriddenColumn = this.resolveOverriddenColumn(); + // pretty sure this is the *specified* table... + return (overriddenColumn == null) ? null : overriddenColumn.getSpecifiedTable(); + } + + public String getDefaultColumnName() { + String overriddenColumnName = this.getOverriddenColumnName(); + return (overriddenColumnName != null) ? overriddenColumnName : this.name; + } + + protected String getOverriddenColumnName() { + ReadOnlyColumn overriddenColumn = this.resolveOverriddenColumn(); + return (overriddenColumn == null) ? null : overriddenColumn.getName(); + } + + public Column resolveOverriddenColumn() { + return this.getContainer().resolveOverriddenColumn(this.name); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualColumn.java new file mode 100644 index 0000000000..3cf168ed05 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualColumn.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.Column; +import org.eclipse.jpt.jpa.core.context.JpaContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmVirtualBaseColumn; + +/** + * <code>orm.xml</code> virtual column + */ +public class GenericOrmVirtualColumn + extends AbstractOrmVirtualBaseColumn<OrmVirtualColumn.Owner, Column> + implements OrmVirtualColumn +{ + protected Integer specifiedLength; + protected int defaultLength; + + protected Integer specifiedPrecision; + protected int defaultPrecision; + + protected Integer specifiedScale; + protected int defaultScale; + + + public GenericOrmVirtualColumn(JpaContextNode parent, OrmVirtualColumn.Owner owner) { + super(parent, owner); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + + this.setSpecifiedLength(this.buildSpecifiedLength()); + this.setDefaultLength(this.buildDefaultLength()); + + this.setSpecifiedPrecision(this.buildSpecifiedPrecision()); + this.setDefaultPrecision(this.buildDefaultPrecision()); + + this.setSpecifiedScale(this.buildSpecifiedScale()); + this.setDefaultScale(this.buildDefaultScale()); + } + + + // ********** column ********** + + @Override + public Column getOverriddenColumn() { + return this.owner.resolveOverriddenColumn(); + } + + + // ********** length ********** + + public int getLength() { + return (this.specifiedLength != null) ? this.specifiedLength.intValue() : this.defaultLength; + } + + public Integer getSpecifiedLength() { + return this.specifiedLength; + } + + protected void setSpecifiedLength(Integer length) { + Integer old = this.specifiedLength; + this.specifiedLength = length; + this.firePropertyChanged(SPECIFIED_LENGTH_PROPERTY, old, length); + } + + protected Integer buildSpecifiedLength() { + return this.getOverriddenColumn().getSpecifiedLength(); + } + + public int getDefaultLength() { + return this.defaultLength; + } + + protected void setDefaultLength(int length) { + int old = this.defaultLength; + this.defaultLength = length; + this.firePropertyChanged(DEFAULT_LENGTH_PROPERTY, old, length); + } + + protected int buildDefaultLength() { + return DEFAULT_LENGTH; + } + + + // ********** precision ********** + + public int getPrecision() { + return (this.specifiedPrecision != null) ? this.specifiedPrecision.intValue() : this.defaultPrecision; + } + + public Integer getSpecifiedPrecision() { + return this.specifiedPrecision; + } + + protected void setSpecifiedPrecision(Integer precision) { + Integer old = this.specifiedPrecision; + this.specifiedPrecision = precision; + this.firePropertyChanged(SPECIFIED_PRECISION_PROPERTY, old, precision); + } + + protected Integer buildSpecifiedPrecision() { + return this.getOverriddenColumn().getSpecifiedPrecision(); + } + + public int getDefaultPrecision() { + return this.defaultPrecision; + } + + protected void setDefaultPrecision(int precision) { + int old = this.defaultPrecision; + this.defaultPrecision = precision; + this.firePropertyChanged(DEFAULT_PRECISION_PROPERTY, old, precision); + } + + protected int buildDefaultPrecision() { + return DEFAULT_PRECISION; + } + + + // ********** scale ********** + + public int getScale() { + return (this.specifiedScale != null) ? this.specifiedScale.intValue() : this.defaultScale; + } + + public Integer getSpecifiedScale() { + return this.specifiedScale; + } + + protected void setSpecifiedScale(Integer scale) { + Integer old = this.specifiedScale; + this.specifiedScale = scale; + this.firePropertyChanged(SPECIFIED_SCALE_PROPERTY, old, scale); + } + + protected Integer buildSpecifiedScale() { + return this.getOverriddenColumn().getSpecifiedScale(); + } + + public int getDefaultScale() { + return this.defaultScale; + } + + protected void setDefaultScale(int scale) { + int old = this.defaultScale; + this.defaultScale = scale; + this.firePropertyChanged(DEFAULT_SCALE_PROPERTY, old, scale); + } + + protected int buildDefaultScale() { + return DEFAULT_SCALE; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualJoinColumn.java new file mode 100644 index 0000000000..ceaef0bc75 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualJoinColumn.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.JoinColumn; +import org.eclipse.jpt.jpa.core.context.JpaContextNode; +import org.eclipse.jpt.jpa.core.context.ReadOnlyJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualJoinColumn; +import org.eclipse.jpt.jpa.core.internal.context.MappingTools; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmVirtualBaseColumn; + +/** + * <code>orm.xml</code> virtual join column + */ +public class GenericOrmVirtualJoinColumn + extends AbstractOrmVirtualBaseColumn<ReadOnlyJoinColumn.Owner, JoinColumn> + implements OrmVirtualJoinColumn +{ + protected final JoinColumn overriddenColumn; + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericOrmVirtualJoinColumn(JpaContextNode parent, ReadOnlyJoinColumn.Owner owner, JoinColumn overriddenColumn) { + super(parent, owner); + this.overriddenColumn = overriddenColumn; + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + + this.setSpecifiedReferencedColumnName(this.buildSpecifiedReferencedColumnName()); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** column ********** + + @Override + public JoinColumn getOverriddenColumn() { + return this.overriddenColumn; + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + protected void setSpecifiedReferencedColumnName(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return this.getOverriddenColumn().getSpecifiedReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultReferencedColumnName() { + return MappingTools.buildJoinColumnDefaultReferencedColumnName(this.owner); + } + + + // ********** misc ********** + + @Override + protected String buildDefaultName() { + return MappingTools.buildJoinColumnDefaultName(this, this.owner); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualOverrideRelationship.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualOverrideRelationship.java new file mode 100644 index 0000000000..f8211eddf6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualOverrideRelationship.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.Entity; +import org.eclipse.jpt.jpa.core.context.OverrideRelationship; +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.orm.OrmVirtualAssociationOverride; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualJoinTableRelationshipStrategy; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.internal.context.orm.GenericOrmVirtualOverrideJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.jpa2.context.orm.GenericOrmVirtualOverrideJoinTableRelationshipStrategy2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmVirtualOverrideRelationship2_0; + +public class GenericOrmVirtualOverrideRelationship + extends AbstractOrmXmlContextNode + implements OrmVirtualOverrideRelationship2_0 +{ + protected OrmVirtualRelationshipStrategy strategy; + + protected final OrmVirtualJoinColumnRelationshipStrategy joinColumnStrategy; + + // JPA 2.0 + protected final OrmVirtualJoinTableRelationshipStrategy joinTableStrategy; + + + public GenericOrmVirtualOverrideRelationship(OrmVirtualAssociationOverride parent) { + super(parent); + this.joinColumnStrategy = this.buildJoinColumnStrategy(); + this.joinTableStrategy = this.buildJoinTableStrategy(); + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.setStrategy(this.buildStrategy()); + this.joinColumnStrategy.update(); + this.joinTableStrategy.update(); + } + + + // ********** strategy ********** + + public OrmVirtualRelationshipStrategy getStrategy() { + return this.strategy; + } + + protected void setStrategy(OrmVirtualRelationshipStrategy strategy) { + OrmVirtualRelationshipStrategy old = this.strategy; + this.strategy = strategy; + this.firePropertyChanged(STRATEGY_PROPERTY, old, strategy); + } + + protected OrmVirtualRelationshipStrategy buildStrategy() { + if (this.isJpa2_0Compatible()) { + if (this.joinColumnStrategy.hasSpecifiedJoinColumns()) { + return this.joinColumnStrategy; + } + return this.joinTableStrategy; + } + return this.joinColumnStrategy; + } + + + // ********** join column strategy ********** + + public OrmVirtualJoinColumnRelationshipStrategy getJoinColumnStrategy() { + return this.joinColumnStrategy; + } + + public boolean strategyIsJoinColumn() { + return this.strategy == this.joinColumnStrategy; + } + + public boolean mayHaveDefaultJoinColumn() { + return false; + } + + protected OrmVirtualJoinColumnRelationshipStrategy buildJoinColumnStrategy() { + return new GenericOrmVirtualOverrideJoinColumnRelationshipStrategy(this); + } + + + // ********** join table strategy ********** + + public OrmVirtualJoinTableRelationshipStrategy getJoinTableStrategy() { + return this.joinTableStrategy; + } + + public boolean strategyIsJoinTable() { + return this.strategy == this.joinTableStrategy; + } + + public boolean mayHaveDefaultJoinTable() { + return this.isVirtual(); + } + + protected OrmVirtualJoinTableRelationshipStrategy buildJoinTableStrategy() { + return new GenericOrmVirtualOverrideJoinTableRelationshipStrategy2_0(this); + } + + + // ********** conversions ********** + + public void initializeOn(Relationship newRelationship) { + newRelationship.initializeFromJoinTableRelationship(this); + newRelationship.initializeFromJoinColumnRelationship(this); + } + + public void initializeOnSpecified(OverrideRelationship specifiedRelationship) { + specifiedRelationship.initializeFromVirtualJoinColumnRelationship(this); + specifiedRelationship.initializeFromVirtualJoinTableRelationship(this); + } + + + // ********** misc ********** + + @Override + public OrmVirtualAssociationOverride getParent() { + return (OrmVirtualAssociationOverride) super.getParent(); + } + + public OrmVirtualAssociationOverride getAssociationOverride() { + return this.getParent(); + } + + public TypeMapping getTypeMapping() { + return this.getAssociationOverride().getContainer().getTypeMapping(); + } + + public Entity getEntity() { + TypeMapping typeMapping = this.getTypeMapping(); + return (typeMapping instanceof Entity) ? (Entity) typeMapping : null; + } + + public boolean isVirtual() { + return true; + } + + public RelationshipMapping getMapping() { + return this.getAssociationOverride().getMapping(); + } + + public Relationship resolveOverriddenRelationship() { + return this.getAssociationOverride().resolveOverriddenRelationship(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualPrimaryKeyJoinColumn.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualPrimaryKeyJoinColumn.java new file mode 100644 index 0000000000..d85905fd19 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualPrimaryKeyJoinColumn.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.ReadOnlyBaseJoinColumn; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.java.JavaPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualPrimaryKeyJoinColumn; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmVirtualNamedColumn; + +/** + * <code>orm.xml</code> virtual primary key join column + */ +public class GenericOrmVirtualPrimaryKeyJoinColumn + extends AbstractOrmVirtualNamedColumn<ReadOnlyBaseJoinColumn.Owner, JavaPrimaryKeyJoinColumn> + implements OrmVirtualPrimaryKeyJoinColumn +{ + protected final JavaPrimaryKeyJoinColumn overriddenColumn; + + protected String specifiedReferencedColumnName; + protected String defaultReferencedColumnName; + + + public GenericOrmVirtualPrimaryKeyJoinColumn(XmlContextNode parent, ReadOnlyBaseJoinColumn.Owner owner, JavaPrimaryKeyJoinColumn overriddenColumn) { + super(parent, owner); + this.overriddenColumn = overriddenColumn; + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + + this.setSpecifiedReferencedColumnName(this.buildSpecifiedReferencedColumnName()); + this.setDefaultReferencedColumnName(this.buildDefaultReferencedColumnName()); + } + + + // ********** column ********** + + @Override + public JavaPrimaryKeyJoinColumn getOverriddenColumn() { + return this.overriddenColumn; + } + + public boolean isDefault() { + return this.owner.joinColumnIsDefault(this); + } + + + // ********** referenced column name ********** + + public String getReferencedColumnName() { + return (this.specifiedReferencedColumnName != null) ? this.specifiedReferencedColumnName : this.defaultReferencedColumnName; + } + + public String getSpecifiedReferencedColumnName() { + return this.specifiedReferencedColumnName; + } + + protected void setSpecifiedReferencedColumnName(String name) { + String old = this.specifiedReferencedColumnName; + this.specifiedReferencedColumnName = name; + this.firePropertyChanged(SPECIFIED_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildSpecifiedReferencedColumnName() { + return this.getOverriddenColumn().getSpecifiedReferencedColumnName(); + } + + public String getDefaultReferencedColumnName() { + return this.defaultReferencedColumnName; + } + + protected void setDefaultReferencedColumnName(String name) { + String old = this.defaultReferencedColumnName; + this.defaultReferencedColumnName = name; + this.firePropertyChanged(DEFAULT_REFERENCED_COLUMN_NAME_PROPERTY, old, name); + } + + protected String buildDefaultReferencedColumnName() { + return this.buildDefaultName(); + } + + + // ********** misc ********** + + public String getTable() { + return this.owner.getDefaultTableName(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualUniqueConstraint.java new file mode 100644 index 0000000000..6fe8eb779c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmVirtualUniqueConstraint.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.jpa.core.context.UniqueConstraint; +import org.eclipse.jpt.jpa.core.context.XmlContextNode; +import org.eclipse.jpt.jpa.core.context.orm.OrmVirtualUniqueConstraint; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmReadOnlyUniqueConstraint; + +public class GenericOrmVirtualUniqueConstraint + extends AbstractOrmReadOnlyUniqueConstraint + implements OrmVirtualUniqueConstraint +{ + protected final UniqueConstraint overriddenUniqueConstraint; + + + public GenericOrmVirtualUniqueConstraint(XmlContextNode parent, UniqueConstraint overriddenUniqueConstraint) { + super(parent); + this.overriddenUniqueConstraint = overriddenUniqueConstraint; + } + + + // ********** synchronize/update ********** + + @Override + public void update() { + super.update(); + this.syncColumnNames(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return null; + } + + + // ********** misc ********** + + public UniqueConstraint getOverriddenUniqueConstraint() { + return this.overriddenUniqueConstraint; + } + + @Override + protected Iterable<String> getResourceColumnNames() { + return this.overriddenUniqueConstraint.getColumnNames(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXml.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXml.java new file mode 100644 index 0000000000..190e0fa341 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXml.java @@ -0,0 +1,281 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm; + +import java.util.List; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IResource; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.Tools; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +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.orm.EntityMappings; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType; +import org.eclipse.jpt.jpa.core.context.orm.OrmXml; +import org.eclipse.jpt.jpa.core.context.persistence.MappingFileRef; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.orm.XmlEntityMappings; +import org.eclipse.jpt.jpa.core.resource.xml.JpaXmlResource; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.ReplaceEdit; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * JPA <code>orm.xml</code> file. + */ +public class GenericOrmXml + extends AbstractOrmXmlContextNode + implements OrmXml +{ + /** + * If the XML resource's content type changes, the mapping file + * ref will throw out its current mapping file. + */ + protected final JpaXmlResource xmlResource; // never null + + /** + * The resouce type will only change if the XML file's version changes + * (since, if the content type changes, we get garbage-collected). + */ + protected JptResourceType resourceType; + + /** + * The root element of the <code>orm.xml</code> file. + */ + protected EntityMappings root; + + + public GenericOrmXml(MappingFileRef parent, JpaXmlResource xmlResource) { + super(parent); + this.checkXmlResource(xmlResource); + this.xmlResource = xmlResource; + this.resourceType = xmlResource.getResourceType(); + + XmlEntityMappings xmlEntityMappings = (XmlEntityMappings) xmlResource.getRootObject(); + if (xmlEntityMappings != null) { + this.root = this.buildRoot(xmlEntityMappings); + } + } + + + // ********** synchronize/update ********** + + /** + * @see org.eclipse.jpt.jpa.core.internal.jpa1.context.persistence.GenericPersistenceXml#synchronizeWithResourceModel() + */ + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + XmlEntityMappings oldXmlEntityMappings = (this.root == null) ? null : this.root.getXmlEntityMappings(); + XmlEntityMappings newXmlEntityMappings = (XmlEntityMappings) this.xmlResource.getRootObject(); + JptResourceType newResourceType = this.xmlResource.getResourceType(); + + // If the old and new XML entity mappings are different instances, + // we scrap the old context entity mappings and rebuild. + // (This can happen when the resource model changes drastically, + // such as a CVS checkout or an edit reversion.) + if ((oldXmlEntityMappings != newXmlEntityMappings) || + (newXmlEntityMappings == null) || + this.valuesAreDifferent(this.resourceType, newResourceType) + ) { + if (this.root != null) { + this.unregisterRootStructureNode(); + this.root.dispose(); + this.setRoot(null); + } + } + + this.resourceType = newResourceType; + + if (newXmlEntityMappings != null) { + if (this.root == null) { + this.setRoot(this.buildRoot(newXmlEntityMappings)); + } else { + // the context entity mappings already holds the XML entity mappings + this.root.synchronizeWithResourceModel(); + } + } + } + + @Override + public void update() { + super.update(); + if (this.root != null) { + this.root.update(); + // this will happen redundantly - need to hold JpaFile? + this.registerRootStructureNode(); + } + } + + + // ********** root ********** + + public EntityMappings getRoot() { + return this.root; + } + + protected void setRoot(EntityMappings root) { + EntityMappings old = this.root; + this.root = root; + this.firePropertyChanged(ROOT_PROPERTY, old, root); + } + + protected EntityMappings buildRoot(XmlEntityMappings xmlEntityMappings) { + return this.getContextNodeFactory().buildEntityMappings(this, xmlEntityMappings); + } + + + // ********** misc ********** + + protected void checkXmlResource(JpaXmlResource resource) { + if (resource == null) { + throw new NullPointerException(); + } + if ( ! resource.getContentType().isKindOf(JptJpaCorePlugin.MAPPING_FILE_CONTENT_TYPE)) { + throw new IllegalArgumentException("Content type is not 'mapping file': " + resource); //$NON-NLS-1$ + } + } + + @Override + public MappingFileRef getParent() { + return (MappingFileRef) super.getParent(); + } + + @Override + public IResource getResource() { + return this.xmlResource.getFile(); + } + + @Override + public JptResourceType getResourceType() { + return this.resourceType; + } + + protected JpaFile getJpaFile() { + return this.getJpaFile(this.xmlResource.getFile()); + } + + public boolean isIn(IFolder folder) { + IResource member = folder.findMember(this.xmlResource.getFile().getName()); + IFile file = this.xmlResource.getFile(); + return Tools.valuesAreEqual(member, file); + } + + // ********** JpaStructureNode implementation ********** + + public String getId() { + // isn't actually displayed, so needs no details page + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + if ((this.root != null) && this.root.containsOffset(textOffset)) { + return this.root.getStructureNode(textOffset); + } + return this; + } + + // never actually selected + public TextRange getSelectionTextRange() { + return TextRange.Empty.instance(); + } + + public void dispose() { + if (this.root != null) { + JpaFile jpaFile = this.getJpaFile(); + if (jpaFile != null) { + this.unregisterRootStructureNode(); + } + this.root.dispose(); + } + } + + // TODO hold the JpaFile? + protected void registerRootStructureNode() { + this.getJpaFile().addRootStructureNode(this.xmlResource, this.root); + } + + protected void unregisterRootStructureNode() { + this.getJpaFile().removeRootStructureNode(this.xmlResource, this.root); + } + + + // ********** MappingFile implementation ********** + + public JpaXmlResource getXmlResource() { + return this.xmlResource; + } + + public OrmPersistentType getPersistentType(String name) { + return (this.root == null) ? null : this.root.getPersistentType(name); + } + + + // ********** PersistentTypeContainer implementation ********** + + /** + * All <code>orm.xml</code> mapping files must be able to generate a static metamodel + * because 1.0 <code>orm.xml</code> files can be referenced from 2.0 + * <code>persistence.xml</code> + * files. + */ + public Iterable<OrmPersistentType> getPersistentTypes() { + return (this.root != null) ? this.root.getPersistentTypes() : EmptyIterable.<OrmPersistentType>instance(); + } + + + // ********** refactoring ********** + + public Iterable<DeleteEdit> createDeleteTypeEdits(IType type) { + return (this.root != null) ? + this.root.createDeleteTypeEdits(type) : + EmptyIterable.<DeleteEdit>instance(); + } + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return (this.root != null) ? + this.root.createRenameTypeEdits(originalType, newName) : + EmptyIterable.<ReplaceEdit>instance(); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return (this.root != null) ? + this.root.createMoveTypeEdits(originalType, newPackage) : + EmptyIterable.<ReplaceEdit>instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return (this.root != null) ? + this.root.createRenamePackageEdits(originalPackage, newName) : + EmptyIterable.<ReplaceEdit>instance(); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + if (this.root != null) { + this.root.validate(messages, reporter); + } + } + + public TextRange getValidationTextRange() { + return TextRange.Empty.instance(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java new file mode 100644 index 0000000000..3a2dbdaa5a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmXmlDefinition.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.ArrayList; +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.common.utility.internal.CollectionTools; +import org.eclipse.jpt.jpa.core.JptJpaCorePlugin; +import org.eclipse.jpt.jpa.core.context.orm.NullOrmAttributeMappingDefinition; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMappingDefinition; +import org.eclipse.jpt.jpa.core.context.orm.OrmTypeMappingDefinition; +import org.eclipse.jpt.jpa.core.context.orm.OrmXmlContextNodeFactory; +import org.eclipse.jpt.jpa.core.context.orm.OrmXmlDefinition; +import org.eclipse.jpt.jpa.core.internal.GenericJpaPlatformProvider; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.GenericOrmXmlContextNodeFactory; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmBasicMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmEmbeddableDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmEmbeddedIdMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmEmbeddedMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmEntityDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmIdMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmManyToManyMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmManyToOneMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmMappedSuperclassDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmOneToManyMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmOneToOneMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmTransientMappingDefinition; +import org.eclipse.jpt.jpa.core.internal.context.orm.OrmVersionMappingDefinition; +import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory; + +public class GenericOrmXmlDefinition + extends AbstractOrmXmlDefinition +{ + // singleton + private static final OrmXmlDefinition INSTANCE = new GenericOrmXmlDefinition(); + + /** + * Return the singleton + */ + public static OrmXmlDefinition instance() { + return INSTANCE; + } + + + /** + * Enforce singleton usage + */ + private GenericOrmXmlDefinition() { + super(); + } + + public JptResourceType getResourceType() { + return JptJpaCorePlugin.ORM_XML_1_0_RESOURCE_TYPE; + } + + public EFactory getResourceNodeFactory() { + return OrmFactory.eINSTANCE; + } + + @Override + protected OrmXmlContextNodeFactory buildContextNodeFactory() { + return new GenericOrmXmlContextNodeFactory(); + } + + @Override + protected void addTypeMappingDefinitionsTo(ArrayList<OrmTypeMappingDefinition> definitions) { + CollectionTools.addAll(definitions, TYPE_MAPPING_DEFINITIONS); + } + + /** + * Order should not matter here; but we'll use the same order as for Java. + * @see GenericJpaPlatformProvider + */ + protected static final OrmTypeMappingDefinition[] TYPE_MAPPING_DEFINITIONS = new OrmTypeMappingDefinition[] { + OrmEntityDefinition.instance(), + OrmEmbeddableDefinition.instance(), + OrmMappedSuperclassDefinition.instance() + }; + + @Override + protected void addAttributeMappingDefinitionsTo(ArrayList<OrmAttributeMappingDefinition> definitions) { + CollectionTools.addAll(definitions, ATTRIBUTE_MAPPING_DEFINITIONS); + } + + /** + * Order should not matter here; but we'll use the same order as for Java. + * @see GenericJpaPlatformProvider + */ + protected static final OrmAttributeMappingDefinition[] ATTRIBUTE_MAPPING_DEFINITIONS = new OrmAttributeMappingDefinition[] { + OrmTransientMappingDefinition.instance(), + OrmIdMappingDefinition.instance(), + OrmVersionMappingDefinition.instance(), + OrmBasicMappingDefinition.instance(), + OrmEmbeddedMappingDefinition.instance(), + OrmEmbeddedIdMappingDefinition.instance(), + OrmManyToManyMappingDefinition.instance(), + OrmManyToOneMappingDefinition.instance(), + OrmOneToManyMappingDefinition.instance(), + OrmOneToOneMappingDefinition.instance(), + NullOrmAttributeMappingDefinition.instance() + }; +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmConverter.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmConverter.java new file mode 100644 index 0000000000..c0b5200071 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmConverter.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.jpa.core.context.Converter; +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.text.edits.ReplaceEdit; + +public class NullOrmConverter + extends AbstractOrmConverter +{ + public NullOrmConverter(OrmAttributeMapping parent) { + super(parent); + } + + public void initialize() { + // NOP + } + + public Class<? extends Converter> getType() { + return null; + } + + public TextRange getValidationTextRange() { + return null; + } + + + // ********** refactoring ********** + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return EmptyIterable.instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return EmptyIterable.instance(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmJoinColumnRelationshipStrategy.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmJoinColumnRelationshipStrategy.java new file mode 100644 index 0000000000..fb9c4fd2b7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/NullOrmJoinColumnRelationshipStrategy.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.jpa1.context.orm; + +import java.util.ListIterator; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterators.EmptyListIterator; +import org.eclipse.jpt.jpa.core.context.JoinColumn; +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.orm.OrmJoinColumn; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumnRelationship; +import org.eclipse.jpt.jpa.core.context.orm.OrmJoinColumnRelationshipStrategy; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode; +import org.eclipse.jpt.jpa.db.Table; + +/** + * Used by + * {@link org.eclipse.jpt.jpa.core.internal.context.orm.GenericOrmOneToManyRelationship#buildJoinColumnStrategy()} + * in a JPA 1.0 project. + */ +public class NullOrmJoinColumnRelationshipStrategy + extends AbstractOrmXmlContextNode + implements OrmJoinColumnRelationshipStrategy +{ + public NullOrmJoinColumnRelationshipStrategy(OrmJoinColumnRelationship parent) { + super(parent); + } + + + // ********** join columns ********** + + public ListIterator<OrmJoinColumn> joinColumns() { + return EmptyListIterator.<OrmJoinColumn>instance(); + } + + public int joinColumnsSize() { + return 0; + } + + + // ********** specified join columns ********** + + public ListIterator<OrmJoinColumn> specifiedJoinColumns() { + return EmptyListIterator.<OrmJoinColumn>instance(); + } + + public int specifiedJoinColumnsSize() { + return 0; + } + + public boolean hasSpecifiedJoinColumns() { + return false; + } + + public OrmJoinColumn getSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public OrmJoinColumn addSpecifiedJoinColumn() { + throw new UnsupportedOperationException(); + } + + public OrmJoinColumn addSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(JoinColumn joinColumn) { + throw new UnsupportedOperationException(); + } + + public void removeSpecifiedJoinColumn(int index) { + throw new UnsupportedOperationException(); + } + + public void moveSpecifiedJoinColumn(int targetIndex, int sourceIndex) { + throw new UnsupportedOperationException(); + } + + + // ********** default join column ********** + + public OrmJoinColumn getDefaultJoinColumn() { + return null; + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return null; + } + + public String getColumnTableNotValidDescription() { + return null; + } + + + // ********** misc ********** + + @Override + public OrmJoinColumnRelationship getParent() { + return (OrmJoinColumnRelationship) super.getParent(); + } + + public OrmJoinColumnRelationship getRelationship() { + return this.getParent(); + } + + public void initializeFrom(ReadOnlyJoinColumnRelationshipStrategy oldStrategy) { + // NOP + } + + public void initializeFromVirtual(ReadOnlyJoinColumnRelationshipStrategy oldStrategy) { + // NOP + } + + public void addStrategy() { + // NOP + } + + public void removeStrategy() { + // NOP + } + + public boolean isTargetForeignKey() { + return false; + } + + public TypeMapping getRelationshipTarget() { + return null; + } + + public String getTableName() { + return null; + } + + public boolean isOverridable() { + return false; + } + + public boolean tableNameIsInvalid(String tableName) { + return true; + } + + public Table resolveDbTable(String tableName) { + return null; + } + + public TypeMapping getRelationshipSource() { + return this.getRelationshipMapping().getTypeMapping(); + } + + protected RelationshipMapping getRelationshipMapping() { + return this.getRelationship().getMapping(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java new file mode 100644 index 0000000000..1cba7cb9d6 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/UnsupportedOrmAttributeMapping.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm; + +import org.eclipse.jpt.jpa.core.context.orm.OrmAttributeMapping; +import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute; +import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmAttributeMapping; +import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField; +import org.eclipse.jpt.jpa.core.resource.orm.Attributes; +import org.eclipse.jpt.jpa.core.resource.orm.XmlNullAttributeMapping; + +/** + * This will be used in cases where Java-supported attribute mapping types + * are not supported by the particular version of the <code>orm.xml</code> + * file. For example, EclipseLink supports variable 1:1 mappings, but the + * generic <code>orm.xml</code> file does not. + */ +public class UnsupportedOrmAttributeMapping + extends AbstractOrmAttributeMapping<XmlNullAttributeMapping> +{ + public UnsupportedOrmAttributeMapping(OrmPersistentAttribute parent, XmlNullAttributeMapping xmlMapping) { + super(parent, xmlMapping); + } + + public String getKey() { + //this ends up returning the java attribute mapping key + return this.xmlAttributeMapping.getMappingKey(); + } + + public int getXmlSequence() { + return -1; + } + + public void initializeOn(OrmAttributeMapping newMapping) { + newMapping.initializeFromOrmAttributeMapping(this); + } + + public void addXmlAttributeMappingTo(Attributes xmlAttributes) { + throw new UnsupportedOperationException(); + } + + public void removeXmlAttributeMappingFrom(Attributes xmlAttributes) { + throw new UnsupportedOperationException(); + } + + + // ********** metamodel ********** + + @Override + public MetamodelField getMetamodelField() { + return null; + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericClassRef.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericClassRef.java new file mode 100644 index 0000000000..96ae45722e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericClassRef.java @@ -0,0 +1,378 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import java.util.Iterator; +import java.util.List; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.common.utility.internal.Tools; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable; +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.java.JavaPersistentType; +import org.eclipse.jpt.jpa.core.context.persistence.ClassRef; +import org.eclipse.jpt.jpa.core.context.persistence.MappingFileRef; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceStructureNodes; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +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.JavaResourcePersistentType; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlJavaClassRef; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.ReplaceEdit; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>persistence.xml</code> file + * <br> + * <code>class</code> element + */ +public class GenericClassRef + extends AbstractPersistenceXmlContextNode + implements ClassRef +{ + /** + * This is <code>null</code> for a <em>virtual</em> class ref. + */ + protected final XmlJavaClassRef xmlJavaClassRef; + + protected String className; + + /** + * The Java persistent type corresponding to the ref's class name; + * this can be <code>null</code> if the name is invalid. + */ + protected JavaPersistentType javaPersistentType; + + + // ********** constructors ********** + + /** + * Construct a <em>specified</em> class ref; i.e. a class ref with + * an explicit entry in the <code>persistence.xml</code>. + */ + public GenericClassRef(PersistenceUnit parent, XmlJavaClassRef xmlJavaClassRef) { + this(parent, xmlJavaClassRef, xmlJavaClassRef.getJavaClass()); + } + + /** + * Construct an <em>virtual</em> class ref; i.e. a class ref without + * an explicit entry in the <code>persistence.xml</code>. + */ + public GenericClassRef(PersistenceUnit parent, String className) { + this(parent, null, className); + } + + protected GenericClassRef(PersistenceUnit parent, XmlJavaClassRef xmlJavaClassRef, String className) { + super(parent); + this.xmlJavaClassRef = xmlJavaClassRef; + this.className = className; + // 'javaPersistentType' is resolved in the update + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + // virtual class refs are matched by name in the persistence unit + // so no need to sync it here (also, 'xmlJavaClassRef' is null...) + if (this.isNotVirtual()) { + // the name probably never changes... + this.setClassName_(this.xmlJavaClassRef.getJavaClass()); + } + if (this.javaPersistentType != null) { + this.javaPersistentType.synchronizeWithResourceModel(); + } + } + + @Override + public void update() { + super.update(); + this.updateJavaPersistentType(); + } + + + // ********** class name ********** + + public String getClassName() { + return this.className; + } + + public void setClassName(String className) { + if (this.isVirtual()) { + throw new IllegalStateException("The name of a virtual class ref cannot be changed: " + this); //$NON-NLS-1$ + } + this.setClassName_(className); + this.xmlJavaClassRef.setJavaClass(className); + } + + protected void setClassName_(String className) { + String old = this.className; + this.className = className; + this.firePropertyChanged(CLASS_NAME_PROPERTY, old, className); + } + + /** + * Nested classes will be qualified with a '$'; the Java name is qualified + * with a '.'. Like <code>className</code>, this can be <code>null</code>. + */ + protected String getJavaClassName() { + return StringTools.stringIsEmpty(this.className) ? null : this.className.replace('$', '.'); + } + + + // ********** java persistent type ********** + + public JavaPersistentType getJavaPersistentType() { + return this.javaPersistentType; + } + + protected void setJavaPersistentType(JavaPersistentType javaPersistentType) { + JavaPersistentType old = this.javaPersistentType; + this.javaPersistentType = javaPersistentType; + this.firePropertyChanged(JAVA_PERSISTENT_TYPE_PROPERTY, old, javaPersistentType); + } + + protected void updateJavaPersistentType() { + JavaResourcePersistentType resourceType = this.resolveJavaResourcePersistentType(); + if (resourceType == null) { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(null); + } + } else { + if (this.javaPersistentType == null) { + this.setJavaPersistentType(this.buildJavaPersistentType(resourceType)); + } else { + if (this.javaPersistentType.getResourcePersistentType() == resourceType) { + this.javaPersistentType.update(); + } else { + this.javaPersistentType.dispose(); + this.setJavaPersistentType(this.buildJavaPersistentType(resourceType)); + } + } + } + } + + protected JavaResourcePersistentType resolveJavaResourcePersistentType() { + String javaClassName = this.getJavaClassName(); + return (javaClassName == null) ? null : this.getJpaProject().getJavaResourcePersistentType(javaClassName); + } + + protected JavaPersistentType buildJavaPersistentType(JavaResourcePersistentType jrpt) { + return this.getJpaFactory().buildJavaPersistentType(this, jrpt); + } + + + // ********** misc ********** + + @Override + public PersistenceUnit getParent() { + return (PersistenceUnit) super.getParent(); + } + + public XmlJavaClassRef getXmlClassRef() { + return this.xmlJavaClassRef; + } + + protected boolean isFor(IType type) { + return this.isFor(type.getFullyQualifiedName('.')); + } + + public boolean isFor(String typeName) { + return Tools.valuesAreEqual(typeName, this.getJavaClassName()); + } + + protected boolean isInPackage(IPackageFragment packageFragment) { + return Tools.valuesAreEqual(this.getPackageName(), packageFragment.getElementName()); + } + + protected String getPackageName() { + int lastPeriod = this.className.lastIndexOf('.'); + return (lastPeriod == -1) ? null : this.className.substring(0, lastPeriod); + } + + public boolean isVirtual() { + return this.xmlJavaClassRef == null; + } + + protected boolean isNotVirtual() { + return ! this.isVirtual(); + } + + public boolean containsOffset(int textOffset) { + return this.isNotVirtual() && this.xmlJavaClassRef.containsOffset(textOffset); + } + + @Override + public void toString(StringBuilder sb) { + sb.append(this.getJavaClassName()); + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return PersistenceStructureNodes.CLASS_REF_ID; + } + + public JpaStructureNode getStructureNode(int textOffset) { + return this; + } + + public TextRange getSelectionTextRange() { + return this.isVirtual() ? null : this.xmlJavaClassRef.getSelectionTextRange(); + } + + public void dispose() { + if (this.javaPersistentType != null) { + this.javaPersistentType.dispose(); + } + } + + + // ********** PersistentType.Owner implementation ********** + + public AccessType getOverridePersistentTypeAccess() { + // no access type at this level overrides any local access type specification + return null; + } + + public AccessType getDefaultPersistentTypeAccess() { + return this.getPersistenceUnit().getDefaultAccess(); + } + + + //*********** refactoring *********** + + public Iterable<DeleteEdit> createDeleteTypeEdits(final IType type) { + if (this.isVirtual()) { + throw new IllegalStateException(); + } + return this.isFor(type) ? + new SingleElementIterable<DeleteEdit>(this.createDeleteEdit()) : + EmptyIterable.<DeleteEdit>instance(); + } + + protected DeleteEdit createDeleteEdit() { + return this.xmlJavaClassRef.createDeleteEdit(); + } + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + if (this.isVirtual()) { + throw new IllegalStateException(); + } + return this.isFor(originalType) ? + new SingleElementIterable<ReplaceEdit>(this.createReplaceEdit(originalType, newName)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createReplaceEdit(IType originalType, String newName) { + return this.xmlJavaClassRef.createRenameEdit(originalType, newName); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + if (this.isVirtual()) { + throw new IllegalStateException(); + } + return this.isFor(originalType) ? + new SingleElementIterable<ReplaceEdit>(this.createRenamePackageEdit(newPackage.getElementName())) : + EmptyIterable.<ReplaceEdit>instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + if (this.isVirtual()) { + throw new IllegalStateException(); + } + return this.isInPackage(originalPackage) ? + new SingleElementIterable<ReplaceEdit>(this.createRenamePackageEdit(newName)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createRenamePackageEdit(String newName) { + return this.xmlJavaClassRef.createRenamePackageEdit(newName); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + if (StringTools.stringIsEmpty(this.className)) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_UNSPECIFIED_CLASS, + this, + this.getValidationTextRange() + ) + ); + return; + } + + if (this.javaPersistentType == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_NONEXISTENT_CLASS, + new String[] {this.getJavaClassName()}, + this, + this.getValidationTextRange() + ) + ); + return; + } + + // 190062 validate Java class only if this is the only reference to it + // i.e. the persistence.xml ref is the only ref - none of the mapping + // files reference the same class + boolean validateJavaPersistentType = true; + for (Iterator<MappingFileRef> stream = this.getPersistenceUnit().mappingFileRefsContaining(this.getJavaClassName()); stream.hasNext(); ) { + validateJavaPersistentType = false; + MappingFileRef mappingFileRef = stream.next(); + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.LOW_SEVERITY, + JpaValidationMessages.PERSISTENCE_UNIT_REDUNDANT_CLASS, + new String[] {this.getJavaClassName(), mappingFileRef.getFileName()}, + this, + this.getValidationTextRange() + ) + ); + } + + if (validateJavaPersistentType) { + this.validateJavaPersistentType(messages, reporter); + } + } + + protected void validateJavaPersistentType(List<IMessage> messages, IReporter reporter) { + try { + this.javaPersistentType.validate(messages, reporter); + } catch (Throwable t) { + JptJpaCorePlugin.log(t); + } + } + + public TextRange getValidationTextRange() { + return this.isVirtual() ? null : this.xmlJavaClassRef.getValidationTextRange(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericJarFileRef.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericJarFileRef.java new file mode 100644 index 0000000000..eec257e95c --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericJarFileRef.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.persistence; + +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractJarFileRef; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlJarFileRef; + +/** + * Context JAR file reference (from the persistence unit) + */ +public class GenericJarFileRef + extends AbstractJarFileRef +{ + public GenericJarFileRef(PersistenceUnit parent, XmlJarFileRef xmlJarFileRef) { + super(parent, xmlJarFileRef); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericMappingFileRef.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericMappingFileRef.java new file mode 100644 index 0000000000..45e923a079 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericMappingFileRef.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jpt.common.core.JptCommonCorePlugin; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractMappingFileRef; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlMappingFileRef; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.ReplaceEdit; + +/** + * <code>persistence.xml</code> file + * <br> + * <code>mapping-file</code> element + */ +public class GenericMappingFileRef + extends AbstractMappingFileRef +{ + protected final XmlMappingFileRef xmlMappingFileRef; + + + public GenericMappingFileRef(PersistenceUnit parent, XmlMappingFileRef xmlMappingFileRef) { + super(parent, xmlMappingFileRef.getFileName()); + this.xmlMappingFileRef = xmlMappingFileRef; + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + // set the file name *before* calling super + this.setFileName_(this.xmlMappingFileRef.getFileName()); + super.synchronizeWithResourceModel(); + } + + + // ********** file name ********** + + public void setFileName(String fileName) { + this.setFileName_(fileName); + this.xmlMappingFileRef.setFileName(fileName); + } + + protected void setFileName_(String xmlFileName) { + String old = this.fileName; + this.fileName = xmlFileName; + if (this.firePropertyChanged(FILE_NAME_PROPERTY, old, xmlFileName)) { + if (this.mappingFile != null) { + this.mappingFile.dispose(); + this.setMappingFile(null); + } + } + } + + + // ********** misc ********** + + public XmlMappingFileRef getXmlMappingFileRef() { + return this.xmlMappingFileRef; + } + + public boolean isImplied() { + return false; + } + + public boolean containsOffset(int textOffset) { + return this.xmlMappingFileRef.containsOffset(textOffset); + } + + + // ********** JpaStructureNode implementation ********** + + public TextRange getSelectionTextRange() { + return this.xmlMappingFileRef.getSelectionTextRange(); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.xmlMappingFileRef.getValidationTextRange(); + } + + + // ********** refactoring ********** + + public Iterable<DeleteEdit> createDeleteMappingFileEdits(IFile file) { + return this.isFor(file) ? + new SingleElementIterable<DeleteEdit>(this.createDeleteEdit()) : + EmptyIterable.<DeleteEdit>instance(); + } + + protected DeleteEdit createDeleteEdit() { + return this.xmlMappingFileRef.createDeleteEdit(); + } + + @Override + protected ReplaceEdit createRenameEdit(IFile originalFile, String newName) { + return this.xmlMappingFileRef.createRenameEdit(originalFile, newName); + } + + public Iterable<ReplaceEdit> createRenameFolderEdits(IFolder originalFolder, String newName) { + return this.isIn(originalFolder) ? + new SingleElementIterable<ReplaceEdit>(this.createRenameFolderEdit(originalFolder, newName)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createRenameFolderEdit(IFolder originalFolder, String newName) { + return this.xmlMappingFileRef.createRenameFolderEdit(originalFolder, newName); + } + + @Override + protected ReplaceEdit createMoveEdit(IFile originalFile, IPath runtineDestination) { + return this.xmlMappingFileRef.createMoveEdit(originalFile, runtineDestination); + } + + public Iterable<ReplaceEdit> createMoveFolderEdits(IFolder originalFolder, IPath runtimeDestination) { + return this.isIn(originalFolder) ? + new SingleElementIterable<ReplaceEdit>(this.createMoveEdit(originalFolder, runtimeDestination)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createMoveEdit(IFolder originalFolder, IPath runtimeDestination) { + IProject project = originalFolder.getProject(); + IPath fullPath = originalFolder.getFullPath(); + IPath originalLocation = JptCommonCorePlugin.getResourceLocator(project).getRuntimePath(project, fullPath); + return this.createMoveEdit(originalLocation, runtimeDestination); + } + + protected ReplaceEdit createMoveEdit(IPath originalLocation, IPath runtineDestination) { + return this.xmlMappingFileRef.createMoveEdit(originalLocation, runtineDestination); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistence.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistence.java new file mode 100644 index 0000000000..446be61a1a --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistence.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import java.util.List; +import java.util.ListIterator; + +import org.eclipse.jpt.common.core.utility.TextRange; +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.SingleElementListIterable; +import org.eclipse.jpt.jpa.core.JpaStructureNode; +import org.eclipse.jpt.jpa.core.JptJpaCorePlugin; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceStructureNodes; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceXml; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +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.persistence.Persistence2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.persistence.PersistenceUnit2_0; +import org.eclipse.jpt.jpa.core.resource.persistence.PersistenceFactory; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlPersistence; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlPersistenceUnit; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * <code>persistence.xml</code> file + * <br> + * <code>persistence</code> element + */ +public class GenericPersistence + extends AbstractPersistenceXmlContextNode + implements Persistence2_0 +{ + protected final XmlPersistence xmlPersistence; + + // The implementation here is a single persistence unit, although the API + // is for a list. We want to support multiple persistence units someday.... + protected PersistenceUnit persistenceUnit; + + + public GenericPersistence(PersistenceXml parent, XmlPersistence xmlPersistence) { + super(parent); + this.xmlPersistence = xmlPersistence; + this.initializePersistenceUnits(); + } + + + // ********** synchronize/update ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.syncPersistenceUnits(); + } + + @Override + public void update() { + super.update(); + this.updateNodes(this.getPersistenceUnits()); + } + + + // ********** persistence units ********** + + public ListIterator<PersistenceUnit> persistenceUnits() { + return this.getPersistenceUnits().iterator(); + } + + protected ListIterable<PersistenceUnit> getPersistenceUnits() { + return (this.persistenceUnit == null) ? EmptyListIterable.<PersistenceUnit>instance() : this.getPersistenceUnits_(); + } + + protected ListIterable<PersistenceUnit> getPersistenceUnits_() { + return new SingleElementListIterable<PersistenceUnit>(this.persistenceUnit); + } + + public int persistenceUnitsSize() { + return (this.persistenceUnit == null) ? 0 : 1; + } + + public PersistenceUnit addPersistenceUnit() { + return this.addPersistenceUnit(this.persistenceUnitsSize()); + } + + public PersistenceUnit addPersistenceUnit(int index) { + if ((index > 0) || (this.persistenceUnit != null)) { + throw new IllegalStateException("This implementation does not support multiple persistence units."); //$NON-NLS-1$ + } + XmlPersistenceUnit xmlPersistenceUnit = PersistenceFactory.eINSTANCE.createXmlPersistenceUnit(); + this.persistenceUnit = this.buildPersistenceUnit(xmlPersistenceUnit); + this.xmlPersistence.getPersistenceUnits().add(xmlPersistenceUnit); + this.fireItemAdded(PERSISTENCE_UNITS_LIST, index, this.persistenceUnit); + return this.persistenceUnit; + } + + public void removePersistenceUnit(PersistenceUnit pu) { + if (pu != this.persistenceUnit) { + throw new IllegalArgumentException("Invalid persistence unit: " + pu); //$NON-NLS-1$ + } + this.removePersistenceUnit(0); + } + + public void removePersistenceUnit(int index) { + if ((index > 0) || (this.persistenceUnit == null)) { + throw new IndexOutOfBoundsException("index: " + index); //$NON-NLS-1$ + } + PersistenceUnit old = this.persistenceUnit; + this.persistenceUnit.dispose(); + this.persistenceUnit = null; + this.xmlPersistence.getPersistenceUnits().remove(index); + this.fireItemRemoved(PERSISTENCE_UNITS_LIST, index, old); + } + + // only building one here, until we support multiple persistence units... + protected void initializePersistenceUnits() { + XmlPersistenceUnit xmlPersistenceUnit = this.getXmlPersistenceUnit(); + if (xmlPersistenceUnit != null) { + this.persistenceUnit = this.buildPersistenceUnit(xmlPersistenceUnit); + } + } + + protected void syncPersistenceUnits() { + XmlPersistenceUnit xmlPersistenceUnit = this.getXmlPersistenceUnit(); + if (this.persistenceUnit == null) { + if (xmlPersistenceUnit != null) { + this.addPersistenceUnit_(this.buildPersistenceUnit(xmlPersistenceUnit)); + } + } else { + if (xmlPersistenceUnit == null) { + this.removePersistenceUnit_(); + } else { + if (this.persistenceUnit.getXmlPersistenceUnit() == xmlPersistenceUnit) { + this.persistenceUnit.synchronizeWithResourceModel(); + } else { + this.removePersistenceUnit_(); + this.addPersistenceUnit_(this.buildPersistenceUnit(xmlPersistenceUnit)); + } + } + } + } + + protected XmlPersistenceUnit getXmlPersistenceUnit() { + List<XmlPersistenceUnit> xmlPersistenceUnits = this.xmlPersistence.getPersistenceUnits(); + return xmlPersistenceUnits.isEmpty() ? null : xmlPersistenceUnits.get(0); + } + + protected void addPersistenceUnit_(PersistenceUnit pu) { + this.persistenceUnit = pu; + this.fireItemAdded(PERSISTENCE_UNITS_LIST, 0, pu); + } + + protected void removePersistenceUnit_() { + PersistenceUnit old = this.persistenceUnit; + this.persistenceUnit = null; + old.dispose(); + this.fireItemRemoved(PERSISTENCE_UNITS_LIST, 0, old); + } + + protected PersistenceUnit buildPersistenceUnit(XmlPersistenceUnit xmlPersistenceUnit) { + return this.getContextNodeFactory().buildPersistenceUnit(this, xmlPersistenceUnit); + } + + + // ********** metamodel ********** + + public void initializeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + ((PersistenceUnit2_0) pu).disposeMetamodel(); + } + } + + + // ********** Persistence implementation ********** + + public XmlPersistence getXmlPersistence() { + return this.xmlPersistence; + } + + public boolean containsOffset(int textOffset) { + return (this.xmlPersistence == null) ? false : this.xmlPersistence.containsOffset(textOffset); + } + + + // ********** XmlContextNode implementation ********** + + @Override + public PersistenceXml getParent() { + return (PersistenceXml) super.getParent(); + } + + public TextRange getValidationTextRange() { + return this.xmlPersistence.getValidationTextRange(); + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + return PersistenceStructureNodes.PERSISTENCE_ID; + } + + public JpaStructureNode getStructureNode(int textOffset) { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + if (pu.containsOffset(textOffset)) { + return pu.getStructureNode(textOffset); + } + } + return this; + } + + public TextRange getSelectionTextRange() { + return this.xmlPersistence.getSelectionTextRange(); + } + + public void dispose() { + for (PersistenceUnit pu : this.getPersistenceUnits()) { + pu.dispose(); + } + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + this.validateVersion(messages); + this.checkForMultiplePersistenceUnits(messages); + this.validatePersistenceUnit(messages, reporter); + } + + protected void validateVersion(List<IMessage> messages) { + if (! this.getLatestDocumentVersion().equals(this.xmlPersistence.getVersion())) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.LOW_SEVERITY, + JpaValidationMessages.XML_VERSION_NOT_LATEST, + this, + this.xmlPersistence.getVersionTextRange())); + } + } + + protected String getLatestDocumentVersion() { + return this.getJpaPlatform().getMostRecentSupportedResourceType( + JptJpaCorePlugin.PERSISTENCE_XML_CONTENT_TYPE).getVersion(); + } + + /** + * extraneous persistence units can be + * accessed through the XmlPersistence resource object + */ + protected void checkForMultiplePersistenceUnits(List<IMessage> messages) { + if (this.xmlPersistence.getPersistenceUnits().size() > 1) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.NORMAL_SEVERITY, + JpaValidationMessages.PERSISTENCE_MULTIPLE_PERSISTENCE_UNITS, + this, + this.getValidationTextRange() + ) + ); + } + } + + protected void validatePersistenceUnit(List<IMessage> messages, IReporter reporter) { + if (this.persistenceUnit == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_NO_PERSISTENCE_UNIT, + this, + this.getValidationTextRange() + ) + ); + return; + } + this.persistenceUnit.validate(messages, reporter); + } + +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java new file mode 100644 index 0000000000..d7adff868b --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnit.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import org.eclipse.jpt.jpa.core.context.persistence.Persistence; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceUnit; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlPersistenceUnit; + +/** + * generic <code>persistence-unit</code> + */ +public class GenericPersistenceUnit + extends AbstractPersistenceUnit +{ + public GenericPersistenceUnit(Persistence parent, XmlPersistenceUnit xmlPersistenceUnit) { + super(parent, xmlPersistenceUnit); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java new file mode 100644 index 0000000000..4c37d3d4b7 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceUnitProperty.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IType; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.Tools; +import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; +import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlProperty; +import org.eclipse.text.edits.ReplaceEdit; + +/** + * Straightforward implementation of the persistence unit property. + * Notifies the persistence unit of any changes to the property. + */ +public class GenericPersistenceUnitProperty + extends AbstractPersistenceXmlContextNode + implements PersistenceUnit.Property +{ + protected final XmlProperty xmlProperty; + protected String name; + protected String value; + + + public GenericPersistenceUnitProperty(PersistenceUnit parent, XmlProperty xmlProperty) { + super(parent); + this.xmlProperty = xmlProperty; + this.name = xmlProperty.getName(); + this.value = xmlProperty.getValue(); + } + + @Override + public PersistenceUnit getParent() { + return (PersistenceUnit) super.getParent(); + } + + public XmlProperty getXmlProperty() { + return this.xmlProperty; + } + + + // ********** synchronize ********** + + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + this.setName_(this.xmlProperty.getName()); + this.setValue_(this.xmlProperty.getValue()); + } + + + // ********** name ********** + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.setName_(name); + this.xmlProperty.setName(name); + } + + protected void setName_(String name) { + String old = this.name; + this.name = name; + if (this.firePropertyChanged(NAME_PROPERTY, old, name)) { + this.getParent().propertyNameChanged(old, name, this.value); + } + } + + + // ********** value ********** + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.setValue_(value); + this.xmlProperty.setValue(value); + } + + protected void setValue_(String value) { + String old = this.value; + this.value = value; + if (this.firePropertyChanged(VALUE_PROPERTY, old, value)) { + this.getParent().propertyValueChanged(this.name, value); + } + } + + protected String getValuePackageName() { + return (this.value == null) ? null : this.getValuePackageName_(); + } + + /** + * pre-condition: {@link #value} is not <code>null</code> + */ + protected String getValuePackageName_() { + int lastPeriod = this.value.lastIndexOf('.'); + return (lastPeriod == -1) ? null : this.value.substring(0, lastPeriod); + } + + + // ********** validation ********** + + public TextRange getValidationTextRange() { + return this.xmlProperty.getValidationTextRange(); + } + + + // ********** refactoring ********** + + public Iterable<ReplaceEdit> createRenameTypeEdits(IType originalType, String newName) { + return Tools.valuesAreEqual(this.value, originalType.getFullyQualifiedName('.')) ? + new SingleElementIterable<ReplaceEdit>(this.createRenameTypeEdit(originalType, newName)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createRenameTypeEdit(IType originalType, String newName) { + return this.xmlProperty.createRenameTypeEdit(originalType, newName); + } + + public Iterable<ReplaceEdit> createMoveTypeEdits(IType originalType, IPackageFragment newPackage) { + return Tools.valuesAreEqual(this.value, originalType.getFullyQualifiedName('.')) ? + new SingleElementIterable<ReplaceEdit>(this.createRenamePackageEdit(newPackage.getElementName())) : + EmptyIterable.<ReplaceEdit>instance(); + } + + public Iterable<ReplaceEdit> createRenamePackageEdits(IPackageFragment originalPackage, String newName) { + return Tools.valuesAreEqual(this.getValuePackageName(), originalPackage.getElementName()) ? + new SingleElementIterable<ReplaceEdit>(this.createRenamePackageEdit(newName)) : + EmptyIterable.<ReplaceEdit>instance(); + } + + protected ReplaceEdit createRenamePackageEdit(String newName) { + return this.xmlProperty.createRenamePackageEdit(newName); + } + + + // ********** misc ********** + + @Override + public void toString(StringBuilder sb) { + sb.append(this.name); + sb.append(" = "); //$NON-NLS-1$ + sb.append(this.value); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXml.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXml.java new file mode 100644 index 0000000000..fda1d6c9bf --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXml.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.common.core.utility.TextRange; +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.JpaRootContextNode; +import org.eclipse.jpt.jpa.core.context.persistence.Persistence; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlContextNode; +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.persistence.Persistence2_0; +import org.eclipse.jpt.jpa.core.jpa2.context.persistence.PersistenceXml2_0; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlPersistence; +import org.eclipse.jpt.jpa.core.resource.xml.JpaXmlResource; +import org.eclipse.wst.validation.internal.provisional.core.IMessage; +import org.eclipse.wst.validation.internal.provisional.core.IReporter; + +/** + * context model <code>persistence.xml</code> file + */ +public class GenericPersistenceXml + extends AbstractPersistenceXmlContextNode + implements PersistenceXml2_0 +{ + /** + * If the XML resource's content type changes, the root context + * node will throw out its current persistence XML. + */ + protected final JpaXmlResource xmlResource; // never null + + /** + * The resource type will only change if the XML file's version changes + * (since, if the content type changes, we get garbage-collected). + */ + protected JptResourceType resourceType; + + /** + * The root element of the <code>persistence.xml</code> file. + */ + protected Persistence persistence; + + + public GenericPersistenceXml(JpaRootContextNode parent, JpaXmlResource xmlResource) { + super(parent); + this.checkXmlResource(xmlResource); + this.xmlResource = xmlResource; + this.resourceType = xmlResource.getResourceType(); + + XmlPersistence xmlPersistence = (XmlPersistence) xmlResource.getRootObject(); + if (xmlPersistence != null) { + this.persistence = this.buildPersistence(xmlPersistence); + } + } + + + // ********** synchronize/update ********** + + /** + * @see org.eclipse.jpt.jpa.core.internal.jpa1.context.orm.GenericOrmXml#synchronizeWithResourceModel() + */ + @Override + public void synchronizeWithResourceModel() { + super.synchronizeWithResourceModel(); + XmlPersistence oldXmlPersistence = (this.persistence == null) ? null : this.persistence.getXmlPersistence(); + XmlPersistence newXmlPersistence = (XmlPersistence) this.xmlResource.getRootObject(); + JptResourceType newResourceType = this.xmlResource.getResourceType(); + + // If the old and new XML persistences are different instances, + // we scrap the old context persistence and rebuild. + // (This can happen when the resource model changes drastically, + // such as a CVS checkout or an edit reversion.) + if ((oldXmlPersistence != newXmlPersistence) || + (newXmlPersistence == null) || + this.valuesAreDifferent(this.resourceType, newResourceType) + ) { + if (this.persistence != null) { + this.unregisterRootStructureNode(); + this.persistence.dispose(); + this.setPersistence(null); + } + } + + this.resourceType = newResourceType; + + if (newXmlPersistence != null) { + if (this.persistence == null) { + this.setPersistence(this.buildPersistence(newXmlPersistence)); + } else { + // the context persistence already holds the XML persistence + this.persistence.synchronizeWithResourceModel(); + } + } + } + + @Override + public void update() { + super.update(); + if (this.persistence != null) { + this.persistence.update(); + // this will happen redundantly - need to hold JpaFile? + this.registerRootStructureNode(); + } + } + + + // ********** persistence ********** + + public Persistence getPersistence() { + return this.persistence; + } + + protected void setPersistence(Persistence persistence) { + Persistence old = this.persistence; + this.persistence = persistence; + this.firePropertyChanged(PERSISTENCE_PROPERTY, old, persistence); + } + + protected Persistence buildPersistence(XmlPersistence xmlPersistence) { + return this.getContextNodeFactory().buildPersistence(this, xmlPersistence); + } + + + // ********** misc ********** + + protected void checkXmlResource(JpaXmlResource resource) { + if (resource == null) { + throw new NullPointerException(); + } + if ( ! resource.getContentType().isKindOf(JptJpaCorePlugin.PERSISTENCE_XML_CONTENT_TYPE)) { + throw new IllegalArgumentException("Content type is not 'persistence': " + resource); //$NON-NLS-1$ + } + } + + public JpaXmlResource getXmlResource() { + return this.xmlResource; + } + + @Override + public IResource getResource() { + return this.xmlResource.getFile(); + } + + @Override + public JptResourceType getResourceType() { + return this.xmlResource.getResourceType(); + } + + protected JpaFile getJpaFile() { + return this.getJpaFile(this.xmlResource.getFile()); + } + + + // ********** metamodel ********** + + public void initializeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).initializeMetamodel(); + } + } + + public void synchronizeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).synchronizeMetamodel(); + } + } + + public void disposeMetamodel() { + if (this.persistence != null) { + ((Persistence2_0) this.persistence).disposeMetamodel(); + } + } + + + // ********** JpaStructureNode implementation ********** + + public String getId() { + // isn't actually displayed, so needs no details page + return null; + } + + public JpaStructureNode getStructureNode(int textOffset) { + if (this.persistence.containsOffset(textOffset)) { + return this.persistence.getStructureNode(textOffset); + } + return this; + } + + // never actually selected + public TextRange getSelectionTextRange() { + return TextRange.Empty.instance(); + } + + public void dispose() { + if (this.persistence != null) { + JpaFile jpaFile = this.getJpaFile(); + if (jpaFile != null) { + this.unregisterRootStructureNode(); + } + this.persistence.dispose(); + } + } + + // TODO hold the JpaFile? + protected void registerRootStructureNode() { + this.getJpaFile().addRootStructureNode(this.xmlResource, this.persistence); + } + + protected void unregisterRootStructureNode() { + this.getJpaFile().removeRootStructureNode(this.xmlResource, this.persistence); + } + + + // ********** validation ********** + + @Override + public void validate(List<IMessage> messages, IReporter reporter) { + super.validate(messages, reporter); + + if (this.persistence == null) { + messages.add( + DefaultJpaValidationMessages.buildMessage( + IMessage.HIGH_SEVERITY, + JpaValidationMessages.PERSISTENCE_XML_INVALID_CONTENT, + this + ) + ); + return; + } + + this.persistence.validate(messages, reporter); + } + + // never actually selected + public TextRange getValidationTextRange() { + return TextRange.Empty.instance(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java new file mode 100644 index 0000000000..57d9a22b6e --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/GenericPersistenceXmlDefinition.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Oracle. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0, which accompanies this distribution + * and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Contributors: + * Oracle - initial API and implementation + ******************************************************************************/ +package org.eclipse.jpt.jpa.core.internal.jpa1.context.persistence; + +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.jpt.common.core.JptResourceType; +import org.eclipse.jpt.jpa.core.JptJpaCorePlugin; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceXmlContextNodeFactory; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceXmlDefinition; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractPersistenceXmlDefinition; +import org.eclipse.jpt.jpa.core.internal.context.persistence.GenericPersistenceXmlContextNodeFactory; +import org.eclipse.jpt.jpa.core.resource.persistence.PersistenceFactory; + +public class GenericPersistenceXmlDefinition + extends AbstractPersistenceXmlDefinition +{ + // singleton + private static final PersistenceXmlDefinition INSTANCE = new GenericPersistenceXmlDefinition(); + + /** + * Return the singleton + */ + public static PersistenceXmlDefinition instance() { + return INSTANCE; + } + + + /** + * Enforce singleton usage + */ + private GenericPersistenceXmlDefinition() { + super(); + } + + public JptResourceType getResourceType() { + return JptJpaCorePlugin.PERSISTENCE_XML_1_0_RESOURCE_TYPE; + } + + public EFactory getResourceNodeFactory() { + return PersistenceFactory.eINSTANCE; + } + + @Override + protected PersistenceXmlContextNodeFactory buildContextNodeFactory() { + return new GenericPersistenceXmlContextNodeFactory(); + } +} diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java new file mode 100644 index 0000000000..dca36559d9 --- /dev/null +++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/persistence/ImpliedMappingFileRef.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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.jpa1.context.persistence; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jpt.common.core.utility.TextRange; +import org.eclipse.jpt.common.utility.internal.StringTools; +import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit; +import org.eclipse.jpt.jpa.core.internal.context.persistence.AbstractMappingFileRef; +import org.eclipse.jpt.jpa.core.resource.persistence.XmlMappingFileRef; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.ReplaceEdit; + +/** + * Used by the persistence unit for the + * <code>META-INF/orm.xml</code> file when it is not explicitly listed + * in the <code>persistence.xml</code> file. + */ +public class ImpliedMappingFileRef + extends AbstractMappingFileRef +{ + + // ********** construction/initialization ********** + + public ImpliedMappingFileRef(PersistenceUnit parent, String fileName) { + super(parent, fileName); + } + + + // ********** MappingFileRef implementation ********** + + public XmlMappingFileRef getXmlMappingFileRef() { + throw new UnsupportedOperationException(); + } + + public boolean isImplied() { + return true; + } + + public void setFileName(String fileName) { + throw new UnsupportedOperationException("Cannot set an implied mapping file ref's 'fileName': " + fileName); //$NON-NLS-1$ + } + + public boolean containsOffset(int textOffset) { + return false; + } + + + // ********** JpaStructureNode implementation ********** + + public TextRange getSelectionTextRange() { + return null; + } + + + // ********** XmlContextNode implementation ********** + + public TextRange getValidationTextRange() { + return this.getPersistenceUnit().getValidationTextRange(); + } + + + // ********** refactoring ********** + + public Iterable<DeleteEdit> createDeleteMappingFileEdits(IFile file) { + throw new IllegalStateException("This reference cannot be deleted - it is implied"); //$NON-NLS-1$ + } + + public Iterable<ReplaceEdit> createRenameFolderEdits(IFolder originalFolder, String newName) { + throw new IllegalStateException("This reference cannot be moved - it is implied"); //$NON-NLS-1$ + } + + @Override + protected ReplaceEdit createRenameEdit(IFile originalFile, String newName) { + return this.createReplaceEdit(this.fileName.substring(0, this.fileName.lastIndexOf('/') + 1) + newName); + } + + @Override + protected ReplaceEdit createMoveEdit(IFile originalFile, IPath runtimeDestination) { + return this.createReplaceEdit(runtimeDestination.append(originalFile.getName()).toString()); + } + + protected ReplaceEdit createReplaceEdit(String newMappingFileName) { + StringBuilder sb = new StringBuilder(); + sb.append(StringTools.CR); + sb.append("\t\t<mapping-file>"); //$NON-NLS-1$ + sb.append(newMappingFileName); + sb.append("</mapping-file>"); //$NON-NLS-1$ + int offset = this.getPersistenceUnit().findInsertLocationForMappingFileRef(); + return new ReplaceEdit(offset, 0, sb.toString()); + } + + public Iterable<ReplaceEdit> createMoveFolderEdits(IFolder originalFolder, IPath runtimeDestination) { + throw new IllegalStateException("This reference cannot be moved - it is implied"); //$NON-NLS-1$ + } +} |