| /* |
| * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // 03/19/2009-2.0 dclarke - initial API start |
| // 06/30/2009-2.0 mobrien - finish JPA Metadata API modifications in support |
| // of the Metamodel implementation for EclipseLink 2.0 release involving |
| // Map, ElementCollection and Embeddable types on MappedSuperclass descriptors |
| // - 266912: JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API) |
| // 08/19/2009-2.0 mobrien - Extend Collection support |
| // http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_59:_20090818:_PluralAttribute.elementType_not_set_for_non-lazy_instantiated_Collection_Attribute |
| // 06/14/2010-2.1 mobrien - 314906: getJavaType should return the |
| // collection javaType C in <X,C,V) of <X, List<V>, V> instead off the elementType V |
| // 08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation |
| package org.eclipse.persistence.internal.jpa.metamodel; |
| |
| import jakarta.persistence.metamodel.Bindable; |
| import jakarta.persistence.metamodel.PluralAttribute; |
| import jakarta.persistence.metamodel.Type; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.queries.ContainerPolicy; |
| import org.eclipse.persistence.internal.queries.MapContainerPolicy; |
| import org.eclipse.persistence.logging.AbstractSessionLog; |
| import org.eclipse.persistence.logging.SessionLog; |
| import org.eclipse.persistence.mappings.AggregateCollectionMapping; |
| import org.eclipse.persistence.mappings.CollectionMapping; |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Provides the implementation for the PluralAttribute interface |
| * of the JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API) |
| * <p> |
| * <b>Description</b>: |
| * Instances of the type PluralAttribute represent |
| * persistent collection-valued attributes. |
| * |
| * @see jakarta.persistence.metamodel.PluralAttribute |
| * |
| * @since EclipseLink 1.2 - JPA 2.0 |
| * |
| * @param <X> The type the represented collection belongs to |
| * @param <C> The type of the represented collection |
| * @param <V> The element type of the represented collection |
| * |
| */ |
| public abstract class PluralAttributeImpl<X, C, V> extends AttributeImpl<X, C> implements PluralAttribute<X, C, V> { |
| |
| /** The type representing this collection type **/ |
| private Type<V> elementType; |
| |
| /** |
| * INTERNAL: |
| * Create an Attribute instance with a passed in validation flag (usually set to true only during Metamodel initialization) |
| */ |
| protected PluralAttributeImpl(ManagedTypeImpl<X> managedType, CollectionMapping mapping, boolean validationEnabled) { |
| super(managedType, mapping); |
| // 1) Check the mapping type first |
| // 2) Get the type set on the policy |
| ClassDescriptor elementDesc = mapping.getContainerPolicy().getElementDescriptor(); |
| |
| // Set the element type on this attribute (the value parameter for a MapAttribute) |
| if (elementDesc != null && !(mapping.isMapKeyMapping() || mapping.isDirectMapMapping())) { |
| // Mappings: OneToMany, UnidirectionalOneToMany, ManyToMany |
| this.elementType = getMetamodel().getType(elementDesc.getJavaClass()); |
| } else { |
| // See CollectionContainerPolicy |
| Class attributeClass = null; |
| // TODO: handle AggregateCollectionMapping and verify isAbstractDirectMapping |
| if(mapping.isDirectCollectionMapping() || mapping.isAbstractCompositeDirectCollectionMapping() |
| || mapping.isDirectCollectionMapping()) { |
| /** |
| * The Map Value parameter was set during metadata processing in DirectCollectionMapping.convertClassNamesToClasses() for example. |
| * The attributeClassification is set from the valueField.typeName String instead of the type Class because of the |
| * way that converters shadow the type/typeName in bug# 289487 |
| */ |
| attributeClass = mapping.getAttributeClassification(); |
| /** |
| * REFACTOR |
| * We were unable to get the type because it is not declared as a generic parameter on the method level attribute. |
| * It may be declared on the field. |
| * See design issue 65 - we need a way to parse the signature of the declaration on the java class - if it exists. |
| * http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_65:_20090827:_Handle_DirectCollection_elementType_retrieval_in_the_absence_of_a_generic_type |
| * Example: |
| * |
| * Collection<String> basicCollection; |
| * @BasicCollection |
| * Collection getBasicCollection() |
| */ |
| // Note: a call to managedType.getTypeClassFromAttributeOrMethodLevelAccesso will only return the class of the collection on the method accessor |
| if (null == attributeClass) { |
| //attributeClass = managedType.getTypeClassFromAttributeOrMethodLevelAccessor(mapping); |
| AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_unable_to_determine_element_type_in_absence_of_generic_parameters", this); |
| } |
| } else if(mapping.isMapKeyMapping()) { |
| ContainerPolicy policy = mapping.getContainerPolicy(); |
| if (policy.isMapPolicy()) { |
| MapContainerPolicy mapPolicy = (MapContainerPolicy) mapping.getContainerPolicy(); |
| attributeClass = mapPolicy.getElementClass(); |
| } else { |
| // TODO: refactor: default to the managedType |
| attributeClass = managedType.getJavaType(); |
| } |
| } else if (mapping.isManyToManyMapping() || mapping.isOneToManyMapping()) { |
| // Example: Collection with an instantiated Set/List |
| attributeClass = mapping.getReferenceClass(); |
| } else if (mapping.isAggregateCollectionMapping()) { |
| // get reference class and check if managedType is a MappedSuperclass |
| attributeClass = mapping.getReferenceClass(); |
| } |
| |
| // TODO: refactor exception handling |
| if (null == attributeClass && validationEnabled) { |
| attributeClass = Object.class; |
| AbstractSessionLog.getLog().log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_attribute_class_type_is_null", this); |
| } |
| this.elementType = getMetamodel().getType(attributeClass); |
| } |
| } |
| |
| /** |
| * Return the Java type of the represented object. |
| * If the bindable type of the object is <code>PLURAL_ATTRIBUTE</code>, |
| * the Java element type is returned. If the bindable type is |
| * <code>SINGULAR_ATTRIBUTE</code> or <code>ENTITY_TYPE</code>, |
| * the Java type of the |
| * represented entity or attribute is returned. |
| * @return Java type |
| */ |
| @Override |
| public Class<V> getBindableJavaType() { |
| // For PLURAL_ATTRIBUTE - return the java element type |
| return elementType.getJavaType(); |
| } |
| |
| /** |
| * Return the bindable type of the represented object. |
| * @return bindable type |
| */ |
| @Override |
| public BindableType getBindableType() { |
| return Bindable.BindableType.PLURAL_ATTRIBUTE; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the mapping associated with this PluralAttribute. |
| */ |
| public CollectionMapping getCollectionMapping() { |
| return (CollectionMapping) getMapping(); |
| } |
| |
| /** |
| * Return the collection type. |
| * @return collection type |
| */ |
| @Override |
| public abstract CollectionType getCollectionType(); |
| |
| /** |
| * Return the type representing the element type of the |
| * collection. |
| * @return element type |
| */ |
| @Override |
| public Type<V> getElementType() { |
| return this.elementType; |
| } |
| |
| @Override |
| public boolean isPlural() { |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuffer aBuffer = new StringBuffer(getJavaType().getSimpleName()); |
| aBuffer.append("AttributeImpl["); |
| //aBuffer.append(getElementType()); |
| //aBuffer.append(","); |
| aBuffer.append(getMapping()); |
| aBuffer.append("]"); |
| return aBuffer.toString(); |
| } |
| } |