org.eclipse.persistence.internal.jpa.EntityGraphImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 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:
// 09 Jan 2013-2.5 Gordon Yorke
// - 397772: JPA 2.1 Entity Graph Support
package org.eclipse.persistence.internal.jpa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jakarta.persistence.AttributeNode;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.Subgraph;
import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.PluralAttribute;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.internal.queries.MappedKeyMapContainerPolicy;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.AttributeGroup;
/**
* Concrete JPA EntityGraph class. For this implementation the EntityGraphImpl
* wraps the EclipseLink AttributeGroup type.
*/
public class EntityGraphImpl extends AttributeNodeImpl implements EntityGraph, Subgraph {
protected AttributeGroup attributeGroup;
protected transient boolean isMutable = false;
protected transient ClassDescriptor descriptor;
protected Class classType;
protected Map attributeNodes;
protected EntityGraphImpl(AttributeGroup group, ClassDescriptor descriptor) {
super();
this.attributeGroup = group;
this.classType = descriptor.getJavaClass();
this.isMutable = true;
this.descriptor = descriptor;
}
public EntityGraphImpl(AttributeGroup group) {
super();
this.attributeGroup = group;
this.classType = group.getType();
if (this.classType == null){
this.classType = ClassConstants.Object_Class;
}
}
protected EntityGraphImpl(AttributeGroup group, ClassDescriptor descriptor, String attribute) {
this(group, descriptor);
this.currentAttribute = attribute;
}
@Override
public String getName() {
return attributeGroup.getName();
}
@Override
public void addAttributeNodes(String... attributeNames) {
if (!this.isMutable) {
throw new IllegalStateException("immutable_entitygraph");
}
for (String attrName : attributeNames) {
if (this.descriptor.getMappingForAttributeName(attrName) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("metamodel_managed_type_attribute_not_present", new Object[]{attrName, this.getClassType()}));
}
this.addAttributeNodeImpl(new AttributeNodeImpl(attrName));
//order is important here, must add attribute node to node list before adding to group or it will appear in node list twice.
this.attributeGroup.addAttribute(attrName, (AttributeGroup) null);
}
}
protected void addAttributeNodeImpl(AttributeNodeImpl attributeNode) {
if (this.attributeNodes == null) {
buildAttributeNodes();
}
this.attributeNodes.put(attributeNode.getAttributeName(), attributeNode);
}
@Override
public void addAttributeNodes(Attribute... attribute) {
if (!this.isMutable) {
throw new IllegalStateException("immutable_entitygraph");
}
for (Attribute attrNode : attribute) {
this.addAttributeNodeImpl(new AttributeNodeImpl(attrNode.getName()));
//order is important here, must add attribute node to node list before adding to group or it will appear in node list twice.
this.attributeGroup.addAttribute(attrNode.getName());
}
}
@Override
public Subgraph addSubgraph(Attribute attribute) {
Class type = attribute.getJavaType();
if (attribute.isCollection()) {
type = ((PluralAttribute) attribute).getBindableJavaType();
}
return addSubgraph(attribute.getName(), type);
}
@Override
public Subgraph extends T> addSubgraph(Attribute attribute, Class extends T> type) {
return addSubgraph(attribute.getName(), type);
}
@Override
public Subgraph addSubgraph(String attributeName) {
return this.addSubgraph(attributeName, null);
}
@Override
public Subgraph addSubgraph(String attributeName, Class type) {
if (!this.isMutable) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("immutable_entitygraph"));
}
AttributeNodeImpl node = null;
if (this.attributeNodes != null){
node = this.attributeNodes.get(attributeName);
}
if (node == null){
node = new AttributeNodeImpl(attributeName);
addAttributeNodeImpl(node);
}
AttributeGroup localGroup = null;
DatabaseMapping mapping = descriptor.getMappingForAttributeName(attributeName);
if (mapping == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("metamodel_managed_type_attribute_not_present", new Object[] { attributeName, this.descriptor.getJavaClassName() }));
}
localGroup = new AttributeGroup(attributeName, type, true);
ClassDescriptor targetDesc = mapping.getReferenceDescriptor();
if (type != null && targetDesc.hasInheritance()) {
targetDesc = targetDesc.getInheritancePolicy().getDescriptor(type);
if (targetDesc == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("type_unkown_for_this_attribute", new Object[] { type.getName(), attributeName }));
}
}
EntityGraphImpl entityGraph = new EntityGraphImpl(localGroup, targetDesc, attributeName);
node.addSubgraph(entityGraph);
//order is important here, must add entity graph to node list before adding to group or it will appear in node list twice.
this.attributeGroup.addAttribute(attributeName, localGroup);
return entityGraph;
}
@Override
public Subgraph addKeySubgraph(Attribute attribute) {
if (!this.isMutable) {
throw new IllegalStateException("immutable_entitygraph");
}
Class type = attribute.getJavaType();
if (attribute.isCollection()) {
type = ((PluralAttribute) attribute).getBindableJavaType();
}
return addKeySubgraph(attribute.getName(), type);
}
@Override
public Subgraph extends T> addKeySubgraph(Attribute attribute, Class extends T> type) {
return addKeySubgraph(attribute.getName(), type);
}
@Override
public Subgraph addKeySubgraph(String attributeName) {
return this.addKeySubgraph(attributeName, null);
}
@Override
public Subgraph addKeySubgraph(String attributeName, Class type) {
if (!this.isMutable) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("immutable_entitygraph"));
}
AttributeNodeImpl node = null;
if (this.attributeNodes != null){
node = this.attributeNodes.get(attributeName);
}
if (node == null){
node = new AttributeNodeImpl(attributeName);
addAttributeNodeImpl(node);
}
AttributeGroup localGroup = null;
DatabaseMapping mapping = descriptor.getMappingForAttributeName(attributeName);
if (mapping == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("metamodel_managed_type_attribute_not_present", new Object[] { this.descriptor.getJavaClassName(), attributeName }));
}
if (!mapping.getContainerPolicy().isMappedKeyMapPolicy() && !((MappedKeyMapContainerPolicy) mapping.getContainerPolicy()).isMapKeyAttribute()) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("attribute_is_not_map_with_managed_key", new Object[] { attributeName, descriptor.getJavaClassName() }));
}
localGroup = new AttributeGroup(attributeName, type, true);
ClassDescriptor targetDesc = mapping.getContainerPolicy().getDescriptorForMapKey();
if (type != null && targetDesc.hasInheritance()) {
targetDesc = targetDesc.getInheritancePolicy().getDescriptor(type);
if (targetDesc == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("type_unkown_for_this_attribute", new Object[] { type.getName(), attributeName }));
}
}
EntityGraphImpl entityGraph = new EntityGraphImpl(localGroup, targetDesc, attributeName);
node.addKeySubgraph(entityGraph);
//order is important here, must add entity graph to node list before adding to group or it will appear in node list twice.
this.attributeGroup.addAttributeKey(attributeName, localGroup);
return entityGraph;
}
@Override
public Subgraph extends T> addSubclassSubgraph(Class extends T> type) {
if (!this.isMutable) {
throw new IllegalStateException("immutable_entitygraph");
}
ClassDescriptor targetDesc = this.descriptor;
if (targetDesc.hasInheritance()) {
targetDesc = targetDesc.getInheritancePolicy().getDescriptor(type);
if (targetDesc == null) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("type_unkown_for_this_entity", new Object[] { type.getName(), this.descriptor.getJavaClassName() }));
}
}
AttributeGroup subGroup = new AttributeGroup(this.attributeGroup.getName(), type, true);
this.attributeGroup.getSubClassGroups().put(type, subGroup);
subGroup.setAllSubclasses(this.attributeGroup.getSubClassGroups());
this.attributeGroup.insertSubClass(subGroup);
return new EntityGraphImpl(subGroup, targetDesc);
}
@Override
public List> getAttributeNodes() {
if (this.attributeNodes == null) {
buildAttributeNodes();
}
return new ArrayList(this.attributeNodes.values());
}
@Override
public Class getClassType() {
return this.classType;
}
/**
* @return the attributeGroup
*/
public AttributeGroup getAttributeGroup() {
return attributeGroup;
}
@Override
public String getAttributeName() {
return currentAttribute;
}
protected void buildAttributeNodes() {
//this instance was built from a pre-existing attribute group so we need to rebuild
//and entity graph
this.attributeNodes = new HashMap();
for (AttributeItem item : this.attributeGroup.getItems().values()) {
AttributeNodeImpl node = new AttributeNodeImpl(item.getAttributeName());
ClassDescriptor localDescriptor = null;
if (this.descriptor != null) {
localDescriptor = this.descriptor.getMappingForAttributeName(item.getAttributeName()).getReferenceDescriptor();
}
if (item.getGroups() != null && ! item.getGroups().isEmpty()) {
for (AttributeGroup subGroup : item.getGroups().values()) {
Class type = subGroup.getType();
if (type == null) {
type = ClassConstants.Object_Class;
}
if (localDescriptor != null) {
if (!type.equals(ClassConstants.Object_Class) && localDescriptor.hasInheritance()) {
localDescriptor = localDescriptor.getInheritancePolicy().getDescriptor(type);
}
node.addSubgraph(new EntityGraphImpl(subGroup, localDescriptor));
} else {
node.addSubgraph(new EntityGraphImpl(subGroup));
}
}
}
if (item.getKeyGroups() != null && ! item.getKeyGroups().isEmpty()) {
for (AttributeGroup subGroup : item.getKeyGroups().values()) {
Class type = subGroup.getType();
if (type == null) {
type = ClassConstants.Object_Class;
}
if (localDescriptor != null) {
if (!type.equals(ClassConstants.Object_Class) && localDescriptor.hasInheritance()) {
localDescriptor = localDescriptor.getInheritancePolicy().getDescriptor(type);
}
node.addKeySubgraph(new EntityGraphImpl(subGroup, localDescriptor));
} else {
node.addKeySubgraph(new EntityGraphImpl(subGroup));
}
}
}
this.attributeNodes.put(item.getAttributeName(), node);
}
}
}