blob: 651bcc52efeff88333d98446ff456c565b3acb1e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2013 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0, which accompanies this distribution
* and is available at https://www.eclipse.org/legal/epl-2.0/.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.jpa1.context;
import java.util.Collection;
import java.util.List;
import org.eclipse.jpt.common.core.internal.utility.ValidationMessageTools;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMember;
import org.eclipse.jpt.common.core.resource.java.JavaResourceMethod;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.internal.ClassNameTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.collection.HashBag;
import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.internal.iterable.SubIterableWrapper;
import org.eclipse.jpt.jpa.core.MappingKeys;
import org.eclipse.jpt.jpa.core.context.AccessType;
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.IdTypeMapping;
import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
import org.eclipse.jpt.jpa.core.context.TypeMapping;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
import org.eclipse.jpt.jpa.core.context.java.JavaSpecifiedPersistentAttribute;
import org.eclipse.jpt.jpa.core.internal.context.JpaValidator;
import org.eclipse.jpt.jpa.core.internal.context.java.PropertyAccessor;
import org.eclipse.jpt.jpa.core.jpa2.context.SingleRelationshipMapping2_0;
import org.eclipse.jpt.jpa.core.validation.JptJpaCoreValidationMessages;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
public abstract class AbstractPrimaryKeyValidator
implements JpaValidator
{
private final IdTypeMapping typeMapping;
public static final String[] EMPTY_STRING_ARRAY = StringTools.EMPTY_STRING_ARRAY;
protected AbstractPrimaryKeyValidator(IdTypeMapping typeMapping) {
this.typeMapping = typeMapping;
}
protected IdTypeMapping typeMapping() {
return this.typeMapping;
}
// Return the id class ref that is to be validated
protected IdClassReference idClassReference() {
return typeMapping().getIdClassReference();
}
protected TextRange getAttributeMappingTextRange(AttributeMapping attributeMapping) {
PersistentAttribute attribute = attributeMapping.getPersistentAttribute();
if (attribute.isVirtual()) {
return attribute.getValidationTextRange();
}
return attributeMapping.getValidationTextRange();
}
// 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(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_CLASS
)
);
}
for (AttributeMapping each : getPrimaryKeyMappingsDefinedLocally(typeMapping())) {
messages.add(
ValidationMessageTools.buildValidationMessage(
each.getResource(),
getAttributeMappingTextRange(each),
JptJpaCoreValidationMessages.TYPE_MAPPING_PK_REDEFINED_ID_ATTRIBUTE
)
);
}
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 (! declaresIdClassInHierarchy() && idClassIsRequired()) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
typeMapping().getValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_REQUIRED
)
);
}
}
// only one composite primary key strategy may be used
protected void validateOneOfIdClassOrEmbeddedIdIsUsed(List<IMessage> messages, IReporter reporter) {
if (declaresIdClassLocally()
&& IterableTools.size(typeMapping().getAllAttributeMappings(MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY)) > 0) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
typeMapping().getValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_AND_EMBEDDED_ID_BOTH_USED
)
);
}
}
//only embedded or id, both may not be used
protected void validateOneOfEmbeddedOrIdIsUsed(List<IMessage> messages, IReporter reporter) {
if (definesEmbeddedIdMapping(typeMapping) && definesIdMapping(typeMapping)) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
typeMapping().getValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_AND_EMBEDDED_ID_BOTH_USED
)
);
}
}
// only one embedded id may be used
protected void validateOneEmbeddedId(List<IMessage> messages, IReporter reporter) {
if (IterableTools.size(getEmbeddedIdMappings(typeMapping())) > 1) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
typeMapping().getValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_MULTIPLE_EMBEDDED_ID
)
);
}
}
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(
ValidationMessageTools.buildValidationMessage(
mapsIdRelationshipMapping.getResource(),
getAttributeMappingTextRange(mapsIdRelationshipMapping),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_WITH_MAPS_ID,
mapsIdRelationshipMapping.getName()
)
);
}
AttributeMapping resolvedAttributeMapping =
mapsIdRelationshipMapping.getDerivedIdentity().getMapsIdDerivedIdentityStrategy().getDerivedIdAttributeMapping();
if (resolvedAttributeMapping != null
&& ! ClassNameTools.isAutoboxEquivalent(
resolvedAttributeMapping.getPersistentAttribute().getTypeName(),
getTargetEntityPrimaryKeyTypeName(mapsIdRelationshipMapping))) {
messages.add(
ValidationMessageTools.buildValidationMessage(
mapsIdRelationshipMapping.getResource(),
getAttributeMappingTextRange(mapsIdRelationshipMapping),
JptJpaCoreValidationMessages.TYPE_MAPPING_MAPS_ID_ATTRIBUTE_TYPE_DOES_NOT_AGREE,
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 (JavaSpecifiedPersistentAttribute idClassAttribute : this.getAllIdClassAttributes(idClass)) {
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(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NOT_PRIMARY_KEY,
idClassAttribute.getName()
)
);
}
// the matching attribute's type should agree
String idClassAttributeTypeName = idClassAttribute.getTypeName(idClass);
String attributeMappingTypeName = getTypeNameForIdClass(attributeMapping);
if (attributeMappingTypeName != null // if it's null, there should be
// another failing validation elsewhere
&& ! ClassNameTools.isAutoboxEquivalent(idClassAttributeTypeName, attributeMappingTypeName)) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_TYPE_DOES_NOT_AGREE,
idClassAttribute.getName(),
idClassAttributeTypeName
)
);
}
}
}
if (! foundMatch) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_NO_MATCH,
idClassAttribute.getName()
)
);
}
}
// This is for validating if a type mapping has extra id attributes that do not match
// an attribute on the id class, which is a supplement of the validation right above
for (AttributeMapping attributeMapping : getPrimaryKeyMappings(typeMapping())) {
AccessType type = attributeMapping.getPersistentAttribute().getDeclaringPersistentType().getAccess();
if (type == AccessType.FIELD) {
checkMissingAttribute(idClass, attributeMapping, messages, reporter);
} else if (type == AccessType.PROPERTY) {
// EclipseLink does not care about the existence status of property methods,
// but the matching field in the id class still needs to exist
if (!IterableTools.contains(getIdClassFieldNames(idClass), attributeMapping.getName())) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_DOES_NOT_EXIST,
attributeMapping.getName()
)
);
} else {
// Validation for missing property methods is only for generic platform
checkMissingAttributeWithPropertyAccess(idClass, attributeMapping, messages, reporter);
}
}
}
// This is for validating cases when id class has property-based access
if (typeMapping().getPersistentType().getAccess() == AccessType.PROPERTY) {
validateIdClassAttributesWithPropertyAccess(idClass, messages, reporter);
}
validateIdClassConstructor(idClass, messages, reporter);
}
protected TextRange getIdClassRefValidationTextRange() {
return idClassReference().getValidationTextRange();
}
protected void checkMissingAttribute(JavaPersistentType idClass,
AttributeMapping attributeMapping, List<IMessage> messages, IReporter reporter) {
if (!IterableTools.contains(getIdClassAttributeNames(idClass), attributeMapping.getName())) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_DOES_NOT_EXIST,
attributeMapping.getName()
)
);
}
}
protected abstract void validateIdClassAttributesWithPropertyAccess(
JavaPersistentType idClass, List<IMessage> messages,
IReporter reporter);
protected void validateIdClassConstructor(JavaPersistentType idClass,
List<IMessage> messages, IReporter reporter) {
if (!idClass.getJavaResourceType().hasNoArgConstructor()) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_MISSING_NO_ARG_CONSTRUCTOR,
idClass.getName()
)
);
}
}
protected void checkMissingAttributeWithPropertyAccess(JavaPersistentType idClass,
AttributeMapping attributeMapping,
List<IMessage> messages, IReporter reporter) {
// do nothing
}
protected void validateIdClass_derivedIdMappingMatchingIdClass(
JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) {
Collection<AttributeMapping> errorMappings = new HashBag<AttributeMapping>();
for (AttributeMapping each
: IterableTools.concatenate(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 (IterableTools.size(errorDerivedIdMappings) > 1) {
for (AttributeMapping each : errorDerivedIdMappings) {
addDuplicateIdClassAttributeMatchError(each, messages);
}
}
}
protected void addNoIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_NO_MATCH,
attributeMapping.getName()
)
);
}
protected void addDuplicateIdClassAttributeMatchError(AttributeMapping attributeMapping, List<IMessage> messages) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_ATTRIBUTE_MAPPING_DUPLICATE_MATCH,
attributeMapping.getName()
)
);
}
protected void validateIdClassPropertyMethods(
JavaPersistentType idClass, List<IMessage> messages, IReporter reporter) {
for (JavaSpecifiedPersistentAttribute attribute : getAllIdClassAttributes(idClass)) {
PropertyAccessor accessor = (PropertyAccessor)attribute.getAccessor();
// validate getter method
JavaResourceMethod getter = accessor.getResourceGetter();
if (getter != null) {
validatePropertyMethod(idClass, getter.getMethodName(), messages, reporter);
}
// validate setter method
JavaResourceMethod setter = accessor.getResourceSetter();
if (setter != null) {
validatePropertyMethod(idClass, setter.getMethodName(), messages, reporter);
}
}
}
private void validatePropertyMethod(JavaPersistentType idClass,
String methodName, List<IMessage> messages, IReporter reporter) {
JavaResourceMethod method = idClass.getJavaResourceType().getMethod(methodName);
if (!method.isPublicOrProtected()) {
messages.add(
ValidationMessageTools.buildValidationMessage(
typeMapping().getResource(),
getIdClassRefValidationTextRange(),
JptJpaCoreValidationMessages.TYPE_MAPPING_ID_CLASS_PROPERTY_METHOD_NOT_PUBLIC,
idClass.getJavaResourceType().getTypeBinding().getQualifiedName(),
methodName
)
);
}
}
protected Iterable<String> getIdClassAttributeNames(JavaPersistentType idClass) {
return IterableTools.transform(getAllIdClassAttributes(idClass), PersistentAttribute.NAME_TRANSFORMER);
}
protected Iterable<JavaSpecifiedPersistentAttribute> getAllIdClassAttributes(JavaPersistentType idClass) {
return new SubIterableWrapper<PersistentAttribute, JavaSpecifiedPersistentAttribute>(idClass.getAllAttributes());
}
protected Iterable<String> getIdClassFieldNames(JavaPersistentType idClass) {
return IterableTools.transform(idClass.getJavaResourceType().getFields(), JavaResourceMember.NAME_TRANSFORMER);
}
// **************** convenience methods ********************************************************
// **************** primary key overall ********************************************************
/**
* Return whether an ancestor class has defined any aspect of the primary key
*/
protected boolean definesPrimaryKeyOnAncestor(IdTypeMapping typeMapping) {
for (IdTypeMapping each : typeMapping.getInheritanceHierarchy()) {
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(IdTypeMapping typeMapping) {
return getIdClass(typeMapping) != null
|| ! IterableTools.isEmpty(getPrimaryKeyMappings(typeMapping));
}
/**
* Return true if the type mapping has defined any aspect of a complex primary key
*/
protected boolean definesComplexPrimaryKey(IdTypeMapping 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(IdTypeMapping typeMapping) {
JavaPersistentType idClass = getIdClass(typeMapping);
if (idClass != null) {
return idClass.getName();
}
EmbeddedIdMapping embeddedId = getEmbeddedIdMapping(typeMapping);
if (embeddedId != null) {
return embeddedId.getPersistentAttribute().getTypeName(typeMapping.getPersistentType());
}
IdMapping id = getIdMapping(typeMapping);
if (id != null) {
return id.getPersistentAttribute().getTypeName(typeMapping.getPersistentType());
}
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 (IterableTools.contains(this.getIdMappingKeys(), mappingKey)) {
return true;
}
if (IterableTools.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 = IterableTools.iterable(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 = IterableTools.iterable(SINGLE_RELATIONSHIP_MAPPING_KEYS_ARRAY);
// **************** id class **********************************************
/**
* Return whether an id class is specified on the class locally
*/
protected boolean declaresIdClassLocally() {
return typeMapping().getIdClassReference().isSpecified();
}
/**
* Return whether an id class is specified in the class hierarchy
* either on current class or on the super class
*/
protected boolean declaresIdClassInHierarchy() {
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(IdTypeMapping typeMapping) {
return getIdClass(typeMapping) != null;
}
/**
* Return whether an ancestor class has defined an id class
*/
protected boolean definesIdClassOnAncestor(IdTypeMapping typeMapping) {
for (IdTypeMapping each : typeMapping.getInheritanceHierarchy()) {
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(IdTypeMapping typeMapping) {
for (IdTypeMapping each : typeMapping.getInheritanceHierarchy()) {
if (each.getIdClassReference().getIdClass() != null) {
return each.getIdClassReference().getIdClass();
}
}
return null;
}
// **************** attribute mappings in general *************************
/**
* Return all the attribute mappings of the given type
* mapping with transient attribute mappings being excluded
*/
protected Iterable<AttributeMapping> getAttributeMappings(TypeMapping typeMapping) {
return IterableTools.filter(typeMapping.getAllAttributeMappings(), AttributeMapping.IS_NOT_TRANSIENT);
}
/**
* Return all primary key mappings, defined on and above the type mapping
*/
protected Iterable<AttributeMapping> getPrimaryKeyMappings(TypeMapping typeMapping) {
return IterableTools.concatenate(
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 IterableTools.concatenate(
getIdMappingsDefinedLocally(typeMapping),
getEmbeddedIdMappingsDefinedLocally(typeMapping),
getDerivedIdMappingsDefinedLocally(typeMapping),
getMapsIdMappingsDefinedLocally(typeMapping));
}
protected boolean hasAnyPrimaryKeyMappings(TypeMapping typeMapping) {
return ! IterableTools.isEmpty(getPrimaryKeyMappings(typeMapping));
}
// **************** id mappings *******************************************
protected IdMapping getIdMapping(TypeMapping typeMapping) {
Iterable<IdMapping> idMappings = getIdMappings(typeMapping);
if (IterableTools.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 ! IterableTools.isEmpty(getEmbeddedIdMappings(typeMapping));
}
/**
* Return whether an id is defined for this class, whether that be locally
* or on an ancestor
*/
protected boolean definesIdMapping(TypeMapping typeMapping) {
return ! IterableTools.isEmpty(getIdMappings(typeMapping));
}
protected EmbeddedIdMapping getEmbeddedIdMapping(TypeMapping typeMapping) {
Iterable<EmbeddedIdMapping> embeddedIdMappings = getEmbeddedIdMappings(typeMapping);
if (IterableTools.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 IterableTools.filter(this.getAllSingleRelationshipMappings(typeMapping), SingleRelationshipMapping2_0.TYPE_MAPPING_USES_ID_DERIVED_IDENTITY_STRATEGY);
}
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 IterableTools.concatenate(
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 IterableTools.filter(this.getSingleRelationshipMappings(typeMapping), SingleRelationshipMapping2_0.TYPE_MAPPING_USES_ID_DERIVED_IDENTITY_STRATEGY);
}
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 IterableTools.concatenate(
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 IterableTools.filter(this.getAllSingleRelationshipMappings(typeMapping), SingleRelationshipMapping2_0.TYPE_MAPPING_USES_MAPS_ID_DERIVED_IDENTITY_STRATEGY);
}
protected Iterable<SingleRelationshipMapping2_0> getMapsIdMappingsDefinedLocally(TypeMapping typeMapping) {
return IterableTools.filter(this.getSingleRelationshipMappings(typeMapping), SingleRelationshipMapping2_0.TYPE_MAPPING_USES_MAPS_ID_DERIVED_IDENTITY_STRATEGY);
}
// **************** 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 =
IterableTools.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;
}
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 (IterableTools.contains(this.getIdMappingKeys(), mappingKey)) {
return attributeMapping.getPersistentAttribute().getTypeName(typeMapping().getPersistentType());
}
if (IterableTools.contains(this.getSingleRelationshipMappingKeys(), mappingKey)) {
SingleRelationshipMapping2_0 relationshipMapping = (SingleRelationshipMapping2_0) attributeMapping;
Entity targetEntity = relationshipMapping.getResolvedTargetEntity();
if (targetEntity != null) {
return getPrimaryKeyTypeName(targetEntity);
}
}
return null;
}
}