org.eclipse.persistence.descriptors.InterfacePolicy Maven / Gradle / Ivy
Show all versions of eclipselink Show documentation
/*
* Copyright (c) 1998, 2024 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:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.descriptors;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.ComplexQueryResult;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Purpose: Allows for a descriptor's implemented interfaces to be configured.
* Generally Interface Descriptors are used for 1 of 2 reasons:
* a. Interface descriptors can be used to query across a set of classes that do not share a table.
* b. As a target of a variable one to one mapping.
*
* @since TopLink for Java 2.0
*/
public class InterfacePolicy implements Serializable, Cloneable {
protected List> parentInterfaces;
protected List parentInterfaceNames;
protected List parentDescriptors;
protected List childDescriptors;
protected ClassDescriptor descriptor;
protected Class> implementorDescriptor;
protected String implementorDescriptorClassName;
/**
* INTERNAL:
* Create a new policy.
* Only descriptor involved in interface should have a policy.
*/
public InterfacePolicy() {
this.childDescriptors = new ArrayList<>();
this.parentInterfaces = new ArrayList<>(2);
this.parentInterfaceNames = new ArrayList<>(2);
this.parentDescriptors = new ArrayList<>(2);
}
/**
* INTERNAL:
* Create a new policy.
* Only descriptor involved in interface should have a policy.
*/
public InterfacePolicy(ClassDescriptor descriptor) {
this();
this.descriptor = descriptor;
}
/**
* INTERNAL:
* Add child descriptor to the parent descriptor.
*/
public void addChildDescriptor(ClassDescriptor childDescriptor) {
getChildDescriptors().add(childDescriptor);
}
/**
* INTERNAL:
* Add parent descriptor.
*/
public void addParentDescriptor(ClassDescriptor parentDescriptor) {
getParentDescriptors().add(parentDescriptor);
}
/**
* PUBLIC:
* Add the parent Interface class.
*
* This method should be called once for each parent Interface of the Descriptor.
*/
public void addParentInterface(Class> parentInterface) {
getParentInterfaces().add(parentInterface);
}
public void addParentInterfaceName(String parentInterfaceName) {
getParentInterfaceNames().add(parentInterfaceName);
}
/**
* INTERNAL:
* Return if there are any child descriptors.
*/
public boolean hasChild() {
return !this.childDescriptors.isEmpty();
}
/**
* INTERNAL:
* Return all the child descriptors.
*/
public List getChildDescriptors() {
return childDescriptors;
}
protected ClassDescriptor getDescriptor() {
return descriptor;
}
/**
* INTERNAL:
* Returns the implementor descriptor class.
*/
@SuppressWarnings({"unchecked"})
public Class getImplementorDescriptor() {
return (Class) implementorDescriptor;
}
/**
* INTERNAL:
* Returns the implementor descriptor class name.
*/
public String getImplementorDescriptorClassName() {
if ((implementorDescriptorClassName == null) && (implementorDescriptor != null)) {
implementorDescriptorClassName = implementorDescriptor.getName();
}
return implementorDescriptorClassName;
}
/**
* INTERNAL:
* Return all the parent descriptors.
*/
public List getParentDescriptors() {
return parentDescriptors;
}
/**
* INTERNAL:
* Return the list of parent interfaces.
*/
public List> getParentInterfaces() {
return parentInterfaces;
}
public List getParentInterfaceNames() {
if (parentInterfaceNames.isEmpty() && !parentInterfaces.isEmpty()) {
for (int i = 0; i < parentInterfaces.size(); i++) {
parentInterfaceNames.add(parentInterfaces.get(i).getName());
}
}
return parentInterfaceNames;
}
/**
* INTERNAL:
* Convert all the class-name-based settings in this InheritancePolicy to actual class-based settings.
* This method is used when converting a project that has been built with class names to a project with classes.
* It will also convert referenced classes to the versions of the classes from the classLoader.
*/
public void convertClassNamesToClasses(ClassLoader classLoader) {
List> newParentInterfaces = new ArrayList<>(2);
for (Iterator iterator = getParentInterfaceNames().iterator(); iterator.hasNext(); ) {
String interfaceName = iterator.next();
Class> interfaceClass = null;
newParentInterfaces.add(PrivilegedAccessHelper.callDoPrivilegedWithException(
() -> PrivilegedAccessHelper.getClassForName(interfaceName, true, classLoader),
(ex) -> ValidationException.classNotFoundWhileConvertingClassNames(interfaceName, ex)
));
}
this.parentInterfaces = newParentInterfaces;
}
/**
* INTERNAL:
* Set the vector to store parent interfaces.
*/
public void initialize(AbstractSession session) {
}
/**
* INTERNAL:
* Check if it is a child descriptor.
*/
public boolean isInterfaceChildDescriptor() {
return ((!(parentInterfaces == null) && !parentInterfaces.isEmpty()) ||
(!(parentInterfaceNames == null) && !parentInterfaceNames.isEmpty()));
}
/**
* INTERNAL:
*/
public boolean isTablePerClassPolicy() {
return false;
}
/**
* INTERNAL:
* Select all objects for a concrete descriptor.
*/
protected Object selectAllObjects(ReadAllQuery query) {
ReadAllQuery concreteQuery = (ReadAllQuery)prepareQuery(query);
return query.getSession().executeQuery(concreteQuery, query.getTranslationRow());
}
/**
* INTERNAL:
* Select all objects for a concrete descriptor.
*/
protected ObjectLevelReadQuery prepareQuery(ObjectLevelReadQuery query) {
ObjectLevelReadQuery concreteQuery = null;
Class> javaClass = this.descriptor.getJavaClass();
// PERF: First check the subclass query cache for the prepared query.
boolean shouldPrepare = query.shouldPrepare();
if (shouldPrepare) {
concreteQuery = (ObjectLevelReadQuery)query.getConcreteSubclassQueries().get(javaClass);
}
if (concreteQuery == null) {
concreteQuery = (ObjectLevelReadQuery)query.deepClone();
concreteQuery.setReferenceClass(javaClass);
concreteQuery.setDescriptor(this.descriptor);
// Disable query cache from implementation queries.
concreteQuery.setQueryResultsCachePolicy(null);
concreteQuery.getExpressionBuilder().setQueryClassAndDescriptor(javaClass, this.descriptor);
// Update the selection criteria if needed as well and don't lose
// the translation row.
if (concreteQuery.getQueryMechanism().getSelectionCriteria() != null) {
//make sure query builder is used for the selection criteria as deepClone will create
//two separate builders.
concreteQuery.getExpressionBuilder().setSession(query.getSession().getRootSession(concreteQuery));
concreteQuery.setSelectionCriteria(concreteQuery.getQueryMechanism().getSelectionCriteria().rebuildOn(concreteQuery.getExpressionBuilder()));
}
if (concreteQuery.hasAdditionalFields()) {
List