blob: 85be82151aaca54eb490fc05e263739c83e06a08 [file] [log] [blame]
/*
* 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)
// 07/06/2009-2.0 mobrien - 266912: Introduce IdentifiableTypeImpl between ManagedTypeImpl
// - EntityTypeImpl now inherits from IdentifiableTypeImpl instead of ManagedTypeImpl
// - MappedSuperclassTypeImpl now inherits from IdentifiableTypeImpl instead
// of implementing IdentifiableType indirectly
// 08/06/2010-2.2 mobrien 322018 - reduce protected instance variables to private to enforce encapsulation
package org.eclipse.persistence.internal.jpa.metamodel;
import java.util.HashMap;
import java.util.Map;
import jakarta.persistence.metamodel.MappedSuperclassType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
/**
* <p>
* <b>Purpose</b>: Provides the implementation for the MappedSuperclassType 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 MappedSuperclassType represent mapped
* superclass types.
*
* @see jakarta.persistence.metamodel.MappedSuperclassType
*
* @since EclipseLink 1.2 - JPA 2.0
*
* @param <X> The represented entity type
*/
public class MappedSuperclassTypeImpl<X> extends IdentifiableTypeImpl<X> implements MappedSuperclassType<X> {
/** Item 54: DI 89: explicit UID will avoid performance hit runtime generation of one */
private static final long serialVersionUID = 3770722221322920646L;
/**
* INTERNAL:
* The map of Identifiable types that inherit from this MappedSuperclass.
* The scope of this map is outside of the JPA 2.0 specification and is limited to MappedSuperclass types.
* The types in this map are keyed on the Java class of the inheriting type.
* This map acts as the reverse of all superType fields that point to "this" MappedSuperclass.
**/
private Map<Class, IdentifiableTypeImpl> inheritingIdentifiableTypes;
protected MappedSuperclassTypeImpl(MetamodelImpl metamodel, ClassDescriptor relationalDescriptor) {
super(metamodel, relationalDescriptor);
inheritingIdentifiableTypes = new HashMap<Class, IdentifiableTypeImpl>();
// The supertype field will remain uninstantiated until MetamodelImpl.initialize() is complete
}
/**
* INTERNAL:
* Add an inheriting subclass to the map of Identifiable types that inherit from this mappedSuperclass.
*/
protected void addInheritingType(IdentifiableTypeImpl identifiableType) {
// The Map will always be instantiated in the constructor
inheritingIdentifiableTypes.put(identifiableType.getJavaType(), identifiableType);
}
/**
* INTERNAL:
* Return an instance of a MappedSuperclassType based on the RelationalDescriptor.
*/
protected static MappedSuperclassTypeImpl<?> create(MetamodelImpl metamodel, ClassDescriptor relationalDescriptor) {
MappedSuperclassTypeImpl<?> mappedSuperclassTypeImpl = new MappedSuperclassTypeImpl(metamodel, relationalDescriptor);
return mappedSuperclassTypeImpl;
}
/**
* INTERNAL:
* MappedSuperclasses need special handling to get their type from an inheriting subclass.
* This function determines the type for an attribute by returning the same inherited attribute from a subclass
*/
public AttributeImpl getMemberFromInheritingType(String name) {
AttributeImpl inheritedAttribute = null;
// search the inheriting types map for an attribute matching the attribute name
for(IdentifiableTypeImpl inheritingType : inheritingIdentifiableTypes.values()) {
//Entity types are initialized before MappedSuperclass types. However, it is possible that the inheriting MappedSuperclass is not yet initialized.
Map inheritingTypeMembers = inheritingType.getMembers();
if ((null == inheritingTypeMembers) && inheritingType.isMappedSuperclass()) {
//not initialized
inheritingType.initialize();
inheritingTypeMembers = inheritingType.getMembers();
}
if(inheritingTypeMembers != null && inheritingTypeMembers.containsKey(name)) {
inheritedAttribute = (AttributeImpl)inheritingType.getAttribute(name);
break;
}
}
// we will return a null attribute in the case that a MappedSuperclass has no implementing entities
return inheritedAttribute;
}
/**
* Return the persistence type.
* @return persistence type
*/
@Override
public jakarta.persistence.metamodel.Type.PersistenceType getPersistenceType() {
return PersistenceType.MAPPED_SUPERCLASS;
}
@Override
protected void initialize(){
/**
* Set the javaClass on the descriptor for the current classLoader (normally done in MetadataProject.addMetamodelMappedSuperclass).
* This will ensure the class is both set and is in the right classLoader - even if the class is already set.
* Perform this conversion only for our custom pseudo descriptors for MappedSuperclasses.
* The classLoader should be obtained from the ConversionManager so we handle EE deployments using a shared-library
*/
descriptor.convertClassNamesToClasses(metamodel.getSession().getDatasourcePlatform().getConversionManager().getLoader());
super.initialize();
}
/**
* INTERNAL:
* Return whether this type is an Entity (true) or MappedSuperclass (false) or Embeddable (false)
*/
@Override
public boolean isEntity() {
return false;
}
/**
* INTERNAL:
* Return whether this type is an MappedSuperclass (true) or Entity (false) or Embeddable (false)
*/
@Override
public boolean isMappedSuperclass() {
return !isEntity();
}
}