blob: 10d11930cdc71dc376e5875fbad5f59449058aa7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.context.java;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.ClassName;
import org.eclipse.jpt.common.utility.internal.ReflectionTools;
import org.eclipse.jpt.common.utility.internal.Tools;
import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.jpa.core.JpaStructureNode;
import org.eclipse.jpt.jpa.core.context.AccessType;
import org.eclipse.jpt.jpa.core.context.CollectionMapping;
import org.eclipse.jpt.jpa.core.context.Embeddable;
import org.eclipse.jpt.jpa.core.context.PersistentType;
import org.eclipse.jpt.jpa.core.context.TypeMapping;
import org.eclipse.jpt.jpa.core.context.java.DefaultJavaAttributeMappingDefinition;
import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMappingDefinition;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.java.JavaStructureNodes;
import org.eclipse.jpt.jpa.core.internal.context.JptValidator;
import org.eclipse.jpt.jpa.core.internal.context.PersistentAttributeTextRangeResolver;
import org.eclipse.jpt.jpa.core.jpa2.context.MetamodelField;
import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaPersistentAttribute2_0;
import org.eclipse.jpt.jpa.core.jpa2.resource.java.JPA2_0;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
/**
* Java persistent attributes
*/
public abstract class AbstractJavaPersistentAttribute
extends AbstractJavaJpaContextNode
implements JavaPersistentAttribute2_0
{
protected final JavaResourcePersistentAttribute resourcePersistentAttribute;
protected String name;
protected AccessType defaultAccess;
protected JavaAttributeMapping mapping; // never null
protected String defaultMappingKey;
protected AbstractJavaPersistentAttribute(PersistentType parent, JavaResourcePersistentAttribute resourcePersistentAttribute) {
super(parent);
this.resourcePersistentAttribute = resourcePersistentAttribute;
this.name = resourcePersistentAttribute.getName();
// this is determined directly from the resource model
this.defaultAccess = this.buildDefaultAccess();
// keep non-null at all times
this.mapping = this.buildMapping();
}
// ********** synchronize/update **********
@Override
public void synchronizeWithResourceModel() {
super.synchronizeWithResourceModel();
this.setName(this.resourcePersistentAttribute.getName());
// this is determined directly from the resource model
this.setDefaultAccess(this.buildDefaultAccess());
this.syncMapping();
}
@Override
public void update() {
super.update();
this.updateMapping();
}
// ********** name **********
public String getName() {
return this.name;
}
protected void setName(String name) {
String old = this.name;
this.name = name;
this.firePropertyChanged(NAME_PROPERTY, old, name);
}
// ********** access **********
/**
* Subclasses determine the specified access.
*/
public AccessType getAccess() {
AccessType access = this.getSpecifiedAccess();
return (access != null) ? access : this.defaultAccess;
}
public abstract AccessType getSpecifiedAccess();
public AccessType getDefaultAccess() {
return this.defaultAccess;
}
protected void setDefaultAccess(AccessType access) {
AccessType old = this.defaultAccess;
this.defaultAccess = access;
this.firePropertyChanged(DEFAULT_ACCESS_PROPERTY, old, access);
}
protected AccessType buildDefaultAccess() {
return this.resourcePersistentAttribute.isField() ? AccessType.FIELD : AccessType.PROPERTY;
}
// ********** mapping **********
public JavaAttributeMapping getMapping() {
return this.mapping;
}
/**
* Clients do not set the mapping directly.
* @see #setMappingKey(String)
*/
protected void setMapping(JavaAttributeMapping mapping) {
JavaAttributeMapping old = this.mapping;
this.mapping = mapping;
this.firePropertyChanged(MAPPING_PROPERTY, old, mapping);
}
public String getMappingKey() {
return this.mapping.getKey();
}
/**
* Possible transitions:
* <table border>
* <th>
* <th>null mapping/default<br>
* <code>key = null</code>
* <th>specified mapping A<br>
* <code>key = "A"</code>
* <th>specified mapping B<br>
* <code>key = "B"</code>
* <tr>
* <th>[default] null mapping
* <td>do nothing
* <td>add annotation A<br>
* set new mapping A
* <td>add annotation B<br>
* set new mapping B
* <tr>
* <th>default mapping A
* <td>do nothing
* <td>add annotation A<br>
* <em>re-use</em> default mapping A
* <td>add annotation B<br>
* set new mapping B
* <tr>
* <th>specified mapping A
* <td>remove annotation A<br>
* set new default or null mapping
* <td>do nothing
* <td>remove annotation A<br>
* add annotation B<br>
* set new mapping B
* </table>
* The "do nothing" transitions are handled in this method.
*/
public JavaAttributeMapping setMappingKey(String key) {
if (this.mapping.isDefault()) {
if (key == null) {
// leave the default mapping unchanged
} else {
this.setMappingKey_(key); // replace the default mapping
}
} else {
if (this.valuesAreEqual(key, this.mapping.getKey())) {
// leave the specified mapping unchanged
} else {
this.setMappingKey_(key); // replace the specified mapping
}
}
return this.mapping;
}
/**
* We have either:<ul>
* <li>a <em>default</em> mapping and a non-<code>null</code> key
* </ul>or<ul>
* <li>a <em>specified</em> mapping and a different (possibly
* <code>null</code>) key
* </ul>
*/
protected void setMappingKey_(String key) {
JavaAttributeMappingDefinition definition = this.getSpecifiedMappingDefinition(key);
if (definition == null) {
// our mapping is "specified" and the key is null;
// check for a default definition
definition = this.getDefaultMappingDefinition();
Iterable<String> supportingAnnotationNames = (definition != null) ? definition.getSupportingAnnotationNames() : EmptyIterable.<String>instance();
// clear any mapping annotation(s);
// leave the "default" mapping's supporting annotations;
// if there is no "default" mapping, clear all supporting annotations too(?)
this.setMappingAnnotation(null, supportingAnnotationNames);
} else {
this.setMappingAnnotation(definition);
}
// note: 'definition' can still be null (if the key is null and there is no "default" mapping)
this.setMapping(this.buildMapping(definition));
}
/**
* pre-condition: definition is not <code>null</code>
*/
protected void setMappingAnnotation(JavaAttributeMappingDefinition definition) {
this.setMappingAnnotation(definition.getAnnotationName(), definition.getSupportingAnnotationNames());
}
protected void setMappingAnnotation(String primaryAnnotationName, Iterable<String> supportingAnnotationNames) {
this.resourcePersistentAttribute.setPrimaryAnnotation(primaryAnnotationName, supportingAnnotationNames);
}
protected JavaAttributeMapping buildMapping(JavaAttributeMappingDefinition definition) {
return (definition == null) ? this.buildNullMapping() : this.buildMapping_(definition);
}
protected JavaAttributeMapping buildNullMapping() {
return this.getJpaFactory().buildJavaNullAttributeMapping(this);
}
/**
* pre-condition: definition is not null
* <p>
* If we are converting a <em>default</em> mapping to its <em>specified</em>
* manifestation, we just keep the same mapping and create its annotation.
* We do <em>not</em> do the same thing when converting a <em>specified</em>
* mapping to its <em>default</em> manifestation. We rebuild the
* entire mapping, simplifying the clearing of all its state. We do this
* because we allow clients to modify a <em>default</em> mapping (or any of
* its components) directly,
* modifying its state and triggering a conversion to a <em>specified</em>
* mapping. The only way to convert a <em>specified</em> mapping to a
* <em>default</em> mapping is by {@link #setMappingKey(String) setting the
* mapping key} to <code>null</code>.
*/
protected JavaAttributeMapping buildMapping_(JavaAttributeMappingDefinition definition) {
// 'mapping' is null during construction
if ((this.mapping != null) && this.mapping.isDefault() && Tools.valuesAreEqual(this.mapping.getKey(), definition.getKey())) {
this.mapping.updateDefault(); // since nothing here changes, we need to update the mapping's flag
return this.mapping;
}
return definition.buildMapping(this, this.getJpaFactory());
}
/**
* We only look for a <em>specified</em> mapping here.
* We look for a default mapping during <em>update</em>.
*/
protected JavaAttributeMapping buildMapping() {
return this.buildMapping(this.getSpecifiedMappingDefinition());
}
/**
* Look for a <em>specified</em> mapping and sync our mapping.
*/
protected void syncMapping() {
JavaAttributeMappingDefinition definition = this.getSpecifiedMappingDefinition();
if (definition == null) {
if (this.mapping.isDefault()) {
// null/default => null/default
this.mapping.synchronizeWithResourceModel();
} else {
// specified => null/default
definition = this.getDefaultMappingDefinition();
this.setMapping(this.buildMapping(definition));
}
} else {
if (this.mapping.isDefault()) {
// null/default => specified
this.setMapping(this.buildMapping(definition));
} else {
// specified => specified
if (this.valuesAreEqual(definition.getKey(), this.mapping.getKey())) {
this.mapping.synchronizeWithResourceModel();
} else {
this.setMapping(this.buildMapping(definition));
}
}
}
}
/**
* Return the "specified" mapping definition for the specified key.
*/
protected JavaAttributeMappingDefinition getSpecifiedMappingDefinition(String key) {
if (key == null) {
return null;
}
for (JavaAttributeMappingDefinition definition : this.getSpecifiedMappingDefinitions()) {
if (Tools.valuesAreEqual(definition.getKey(), key)) {
return definition;
}
}
throw new IllegalArgumentException("invalid mapping key: " + key); //$NON-NLS-1$
}
/**
* Return the mapping definition for the mapping currently specified in the
* source code.
*/
protected JavaAttributeMappingDefinition getSpecifiedMappingDefinition() {
for (JavaAttributeMappingDefinition definition : this.getSpecifiedMappingDefinitions()) {
if (definition.isSpecified(this)) {
return definition;
}
}
return null;
}
protected Iterable<JavaAttributeMappingDefinition> getSpecifiedMappingDefinitions() {
return this.getJpaPlatform().getSpecifiedJavaAttributeMappingDefinitions();
}
// ********** default mapping **********
public String getDefaultMappingKey() {
return this.defaultMappingKey;
}
protected void setDefaultMappingKey(String mappingKey) {
String old = this.defaultMappingKey;
this.defaultMappingKey = mappingKey;
this.firePropertyChanged(DEFAULT_MAPPING_KEY_PROPERTY, old, mappingKey);
}
/**
* If a mapping annotation is specified, we would have already set a
* <em>specified</em> mapping in {@link #syncMapping()}. We need only check
* for changes to the <em>default</em> mapping.
*/
protected void updateMapping() {
JavaAttributeMappingDefinition definition = this.getDefaultMappingDefinition();
String newDefaultKey = (definition == null) ? null : definition.getKey();
if (this.mapping.isDefault() && Tools.valuesAreDifferent(this.mapping.getKey(), newDefaultKey)) {
this.setMapping(this.buildMapping(definition)); // the default mapping has changed
} else {
this.mapping.update();
}
this.setDefaultMappingKey(newDefaultKey);
}
protected JavaAttributeMappingDefinition getDefaultMappingDefinition() {
for (DefaultJavaAttributeMappingDefinition definition : this.getDefaultMappingDefinitions()) {
if (definition.isDefault(this)) {
return definition;
}
}
return null;
}
protected Iterable<DefaultJavaAttributeMappingDefinition> getDefaultMappingDefinitions() {
return this.getJpaPlatform().getDefaultJavaAttributeMappingDefinitions();
}
// ********** JpaStructureNode implementation **********
public String getId() {
return JavaStructureNodes.PERSISTENT_ATTRIBUTE_ID;
}
public JpaStructureNode getStructureNode(int textOffset) {
return this;
}
public TextRange getSelectionTextRange() {
return this.getSelectionTextRange(this.buildASTRoot());
}
protected TextRange getSelectionTextRange(CompilationUnit astRoot) {
return this.resourcePersistentAttribute.getNameTextRange(astRoot);
}
protected CompilationUnit buildASTRoot() {
return this.resourcePersistentAttribute.getJavaResourceCompilationUnit().buildASTRoot();
}
public void dispose() {
// nothing to dispose
}
// ********** type **********
/**
* From the JPA spec, when the basic mapping applies:<br>
* If the type of the attribute (field or property) is one of the following
* it must be mapped as <code>@javax.persistence.Basic</code>:<ul>
* <li><code>byte[]</code>
* <li><code>java.lang.Byte[]</code>
* <li><code>char[]</code>
* <li><code>java.lang.Character[]</code>
* <li>primitive types (except <code>void</code>)
* <li>primitive wrappers (except <code>java.lang.Void</code>)
* <li><code>java.lang.String</code>
* <li><code>java.math.BigInteger</code>
* <li><code>java.math.BigDecimal</code>
* <li><code>java.util.Date</code>
* <li><code>java.util.Calendar</code>
* <li><code>java.sql.Date</code>
* <li><code>java.sql.Time</code>
* <li><code>java.sql.Timestamp</code>
* <li><code>enum</code>s
* <li>any other type that implements <code>java.io.Serializable</code>
* </ul>
*/
public boolean typeIsBasic() {
// 'typeName' may include array brackets but not generic type arguments
String typeName = this.getTypeName();
if (typeName == null) {
return false;
}
int arrayDepth = ReflectionTools.getArrayDepthForTypeDeclaration(typeName);
if (arrayDepth > 1) {
return false; // multi-dimensional arrays are not supported
}
if (arrayDepth == 1) {
String elementTypeName = ReflectionTools.getElementTypeNameForTypeDeclaration(typeName, 1);
return this.elementTypeIsValidForBasicArray(elementTypeName);
}
// arrayDepth == 0
if (ClassName.isVariablePrimitive(typeName)) {
return true; // any primitive but 'void'
}
if (ClassName.isVariablePrimitiveWrapper(typeName)) {
return true; // any primitive wrapper but 'java.lang.Void'
}
if (this.typeIsOtherValidBasicType(typeName)) {
return true;
}
if (this.resourcePersistentAttribute.typeIsEnum()) {
return true;
}
if (this.resourcePersistentAttribute.typeIsSubTypeOf(SERIALIZABLE_TYPE_NAME)) {
return true;
}
return false;
}
/**
* Return whether the specified type is a valid element type for
* a one-dimensional array that can default to a basic mapping:<ul>
* <li><code>byte</code>
* <li><code>java.lang.Byte</code>
* <li><code>char</code>
* <li><code>java.lang.Character</code>
* </ul>
*/
protected boolean elementTypeIsValidForBasicArray(String elementTypeName) {
return ArrayTools.contains(VALID_BASIC_ARRAY_ELEMENT_TYPE_NAMES, elementTypeName);
}
protected static final String[] VALID_BASIC_ARRAY_ELEMENT_TYPE_NAMES = {
byte.class.getName(),
char.class.getName(),
java.lang.Byte.class.getName(),
java.lang.Character.class.getName()
};
/**
* Return whether the specified type is among the various "other" types
* that can default to a basic mapping.
*/
protected boolean typeIsOtherValidBasicType(String typeName) {
return ArrayTools.contains(OTHER_VALID_BASIC_TYPE_NAMES, typeName);
}
protected static final String[] OTHER_VALID_BASIC_TYPE_NAMES = {
java.lang.String.class.getName(),
java.math.BigInteger.class.getName(),
java.math.BigDecimal.class.getName(),
java.util.Date.class.getName(),
java.util.Calendar.class.getName(),
java.sql.Date.class.getName(),
java.sql.Time.class.getName(),
java.sql.Timestamp.class.getName(),
};
protected static final String SERIALIZABLE_TYPE_NAME = java.io.Serializable.class.getName();
public String getSingleReferenceTargetTypeName() {
// 'typeName' may include array brackets ("[]")
// but not generic type arguments (e.g. "<java.lang.String>")
String typeName = this.getTypeName();
if (typeName == null) {
return null;
}
if (ReflectionTools.getArrayDepthForTypeDeclaration(typeName) != 0) {
return null; // arrays cannot be entities
}
if (this.typeIsContainer(typeName)) {
return null; // "containers" cannot be entities
}
return typeName;
}
public String getMultiReferenceTargetTypeName() {
return this.getJpaContainerDefinition().getMultiReferenceTargetTypeName(this.resourcePersistentAttribute);
}
public String getMultiReferenceMapKeyTypeName() {
return this.getJpaContainerDefinition().getMultiReferenceMapKeyTypeName(this.resourcePersistentAttribute);
}
/**
* return whether the specified type is one of the container
* types allowed by the JPA spec
*/
protected boolean typeIsContainer(String typeName) {
return this.getJpaContainerDefinition(typeName).isContainer();
}
// ********** misc **********
@Override
public PersistentType getParent() {
return (PersistentType) super.getParent();
}
public PersistentType getOwningPersistentType() {
return this.getParent();
}
public TypeMapping getOwningTypeMapping() {
return this.getOwningPersistentType().getMapping();
}
public JavaPersistentAttribute getJavaPersistentAttribute() {
return this;
}
public JavaResourcePersistentAttribute getResourcePersistentAttribute() {
return this.resourcePersistentAttribute;
}
public String getPrimaryKeyColumnName() {
return this.getMapping().getPrimaryKeyColumnName();
}
public String getTypeName() {
return this.resourcePersistentAttribute.getTypeName();
}
/**
* Java attributes always correspond to attributes in the source code.
*/
public boolean isVirtual() {
return false;
}
public boolean contains(int offset, CompilationUnit astRoot) {
TextRange fullTextRange = this.getFullTextRange(astRoot);
// 'fullTextRange' will be null if the attribute no longer exists in the java;
// the context model can be out of synch with the resource model
// when a selection event occurs before the context model has a
// chance to synch with the resource model via the update thread
return (fullTextRange == null) ? false : fullTextRange.includes(offset);
}
protected TextRange getFullTextRange(CompilationUnit astRoot) {
return this.resourcePersistentAttribute.getTextRange(astRoot);
}
public Embeddable getEmbeddable() {
String typeName = this.getTypeName();
return (typeName == null) ? null : this.getPersistenceUnit().getEmbeddable(typeName);
}
public boolean isField() {
return this.resourcePersistentAttribute.isField();
}
public boolean isProperty() {
return this.resourcePersistentAttribute.isProperty();
}
public boolean isPublic() {
return Modifier.isPublic(this.resourcePersistentAttribute.getModifiers());
}
public boolean isFinal() {
return Modifier.isFinal(this.resourcePersistentAttribute.getModifiers());
}
@Override
public void toString(StringBuilder sb) {
sb.append(this.name);
}
// ********** validation **********
public TextRange getValidationTextRange(CompilationUnit astRoot) {
return this.getSelectionTextRange(astRoot);
}
@Override
public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
super.validate(messages, reporter, astRoot);
this.validateAttribute(messages, reporter, astRoot);
this.getMapping().validate(messages, reporter, astRoot);
}
protected void validateAttribute(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
this.buildAttibuteValidator(astRoot).validate(messages, reporter);
}
protected abstract JptValidator buildAttibuteValidator(CompilationUnit astRoot);
protected PersistentAttributeTextRangeResolver buildTextRangeResolver(CompilationUnit astRoot) {
return new JavaPersistentAttributeTextRangeResolver(this, astRoot);
}
// ********** Java completion proposals **********
@Override
public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot);
if (result != null) {
return result;
}
return this.getMapping().javaCompletionProposals(pos, filter, astRoot);
}
// ********** metamodel **********
public String getMetamodelContainerFieldTypeName() {
return this.getJpaContainerDefinition().getMetamodelContainerFieldTypeName();
}
public String getMetamodelContainerFieldMapKeyTypeName() {
return this.getJpaContainerDefinition().getMetamodelContainerFieldMapKeyTypeName((CollectionMapping) this.getMapping());
}
public String getMetamodelTypeName() {
String typeName = this.getTypeName();
if (typeName == null) {
return MetamodelField.DEFAULT_TYPE_NAME;
}
if (ClassName.isPrimitive(typeName)) {
return ClassName.getWrapperClassName(typeName); // ???
}
return typeName;
}
// ********** JPA container definition **********
public JpaContainerDefinition getJpaContainerDefinition() {
// 'typeName' may include array brackets ("[]")
// but not generic type arguments (e.g. "<java.lang.String>")
return this.getJpaContainerDefinition(this.resourcePersistentAttribute.getTypeName());
}
/**
* Return the JPA container definition corresponding to the specified type;
* return a "null" definition if the specified type is not one of the
* container types allowed by the JPA spec.
*/
protected JpaContainerDefinition getJpaContainerDefinition(String typeName) {
for (JpaContainerDefinition definition : this.getJpaContainerDefinitions()) {
if (definition.getTypeName().equals(typeName)) {
return definition;
}
}
return JpaContainerDefinition.Null.instance();
}
protected Iterable<JpaContainerDefinition> getJpaContainerDefinitions() {
return JPA_CONTAINER_DEFINITIONS;
}
protected static final JpaContainerDefinition[] JPA_CONTAINER_DEFINITION_ARRAY = new JpaContainerDefinition[] {
new CollectionJpaContainerDefinition(java.util.Collection.class, JPA2_0.COLLECTION_ATTRIBUTE),
new CollectionJpaContainerDefinition(java.util.Set.class, JPA2_0.SET_ATTRIBUTE),
new CollectionJpaContainerDefinition(java.util.List.class, JPA2_0.LIST_ATTRIBUTE),
new MapJpaContainerDefinition(java.util.Map.class, JPA2_0.MAP_ATTRIBUTE)
};
protected static final Iterable<JpaContainerDefinition> JPA_CONTAINER_DEFINITIONS = new ArrayIterable<JpaContainerDefinition>(JPA_CONTAINER_DEFINITION_ARRAY);
/**
* Abstract JPA container definition
*/
protected abstract static class AbstractJpaContainerDefinition
implements JpaContainerDefinition
{
protected final String typeName;
protected final String metamodelContainerFieldTypeName;
protected AbstractJpaContainerDefinition(Class<?> containerClass, String metamodelContainerFieldTypeName) {
this(containerClass.getName(), metamodelContainerFieldTypeName);
}
protected AbstractJpaContainerDefinition(String typeName, String metamodelContainerFieldTypeName) {
super();
if ((typeName == null) || (metamodelContainerFieldTypeName == null)) {
throw new NullPointerException();
}
this.typeName = typeName;
this.metamodelContainerFieldTypeName = metamodelContainerFieldTypeName;
}
public String getTypeName() {
return this.typeName;
}
public boolean isContainer() {
return true;
}
public String getMetamodelContainerFieldTypeName() {
return this.metamodelContainerFieldTypeName;
}
}
/**
* Collection JPA container definition
*/
protected static class CollectionJpaContainerDefinition
extends AbstractJpaContainerDefinition
{
protected CollectionJpaContainerDefinition(Class<?> collectionClass, String staticMetamodelTypeDeclarationTypeName) {
super(collectionClass, staticMetamodelTypeDeclarationTypeName);
}
public String getMultiReferenceTargetTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 1) ?
resourcePersistentAttribute.getTypeTypeArgumentName(0) :
null;
}
public String getMultiReferenceMapKeyTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
return null;
}
public String getMetamodelContainerFieldMapKeyTypeName(CollectionMapping mapping) {
return null;
}
public boolean isMap() {
return false;
}
}
/**
* Map JPA container definition
*/
protected static class MapJpaContainerDefinition
extends AbstractJpaContainerDefinition
{
protected MapJpaContainerDefinition(Class<?> mapClass, String staticMetamodelTypeDeclarationTypeName) {
super(mapClass, staticMetamodelTypeDeclarationTypeName);
}
public String getMultiReferenceTargetTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 2) ?
resourcePersistentAttribute.getTypeTypeArgumentName(1) :
null;
}
public String getMultiReferenceMapKeyTypeName(JavaResourcePersistentAttribute resourcePersistentAttribute) {
return (resourcePersistentAttribute.typeTypeArgumentNamesSize() == 2) ?
resourcePersistentAttribute.getTypeTypeArgumentName(0) :
null;
}
public String getMetamodelContainerFieldMapKeyTypeName(CollectionMapping mapping) {
return mapping.getMetamodelFieldMapKeyTypeName();
}
public boolean isMap() {
return true;
}
}
}