org.eclipse.persistence.internal.sessions.CommitOrderDependencyNode 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, 2018 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.internal.sessions;
import java.util.*;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.localization.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
/**
* This wraps a descriptor with information required to compute an order for
* dependencies. The algorithm is a simple topological sort.
*/
public class CommitOrderDependencyNode {
protected CommitOrderCalculator owner;
protected ClassDescriptor descriptor;
protected AbstractSession session;
// These are the descriptors to which we have 1:1 relationships
protected Vector relatedNodes;
protected CommitOrderDependencyNode predecessor;
// Indicates the state of the traversal
protected int traversalState;
static public int NotVisited = 1;
static public int InProgress = 2;
static public int Visited = 3;
// When we first saw this node in the traversal
protected int discoveryTime;
// When we finished visiting this node
protected int finishingTime;
public CommitOrderDependencyNode(CommitOrderCalculator calculator, ClassDescriptor descriptor, AbstractSession session) {
this.owner = calculator;
this.descriptor = descriptor;
this.relatedNodes = new Vector();
this.session = session;
}
public ClassDescriptor getDescriptor() {
return descriptor;
}
public int getFinishingTime() {
return finishingTime;
}
public CommitOrderCalculator getOwner() {
return owner;
}
public CommitOrderDependencyNode getPredecessor() {
return predecessor;
}
public Vector getRelatedNodes() {
return relatedNodes;
}
public boolean hasBeenVisited() {
return (traversalState == Visited);
}
public boolean hasNotBeenVisited() {
return (traversalState == NotVisited);
}
public void markInProgress() {
traversalState = InProgress;
}
public void markNotVisited() {
traversalState = NotVisited;
}
public void markVisited() {
traversalState = Visited;
}
/**
* Add all owned classes for each descriptor through checking the mappings.
* If I have a foreign mapping with a constraint dependency, then add it
* If I'm related to a class, I'm related to all its subclasses and superclasses.
* If my superclass is related to a class, I'm related to it.
*/
public void recordMappingDependencies() {
for (Enumeration mappings = getDescriptor().getMappings().elements();
mappings.hasMoreElements();) {
DatabaseMapping mapping = (DatabaseMapping)mappings.nextElement();
if (mapping.isForeignReferenceMapping()) {
if (((ForeignReferenceMapping)mapping).hasConstraintDependency()) {
Class ownedClass;
ClassDescriptor refDescriptor = ((ForeignReferenceMapping)mapping).getReferenceDescriptor();
if (refDescriptor == null) {
refDescriptor = session.getDescriptor(((ForeignReferenceMapping)mapping).getReferenceClass());
}
ownedClass = refDescriptor.getJavaClass();
if (ownedClass == null) {
throw org.eclipse.persistence.exceptions.DescriptorException.referenceClassNotSpecified(mapping);
}
CommitOrderDependencyNode node = getOwner().nodeFor(ownedClass);
Vector ownedNodes = withAllSubclasses(node);
// I could remove duplicates here, but it's not that big a deal.
Helper.addAllToVector(relatedNodes, ownedNodes);
} else if (((ForeignReferenceMapping)mapping).hasInverseConstraintDependency()) {
Class ownerClass;
ClassDescriptor refDescriptor = ((ForeignReferenceMapping)mapping).getReferenceDescriptor();
if (refDescriptor == null) {
refDescriptor = session.getDescriptor(((ForeignReferenceMapping)mapping).getReferenceClass());
}
ownerClass = refDescriptor.getJavaClass();
if (ownerClass == null) {
throw org.eclipse.persistence.exceptions.DescriptorException.referenceClassNotSpecified(mapping);
}
CommitOrderDependencyNode ownerNode = getOwner().nodeFor(ownerClass);
Vector ownedNodes = withAllSubclasses(this);
// I could remove duplicates here, but it's not that big a deal.
Helper.addAllToVector(ownerNode.getRelatedNodes(), ownedNodes);
}
}
}
}
/**
* Add all owned classes for each descriptor through checking the mappings.
* If I have a foreign mapping with a constraint dependency, then add it
* If I'm related to a class, I'm related to all its subclasses and superclasses.
* If my superclass is related to a class, I'm related to it.
*/
public void recordSpecifiedDependencies() {
for (Enumeration constraintsEnum = getDescriptor().getConstraintDependencies().elements();
constraintsEnum.hasMoreElements();) {
Class ownedClass = (Class)constraintsEnum.nextElement();
CommitOrderDependencyNode node = getOwner().nodeFor(ownedClass);
Vector ownedNodes = withAllSubclasses(node);
// I could remove duplicates here, but it's not that big a deal.
Helper.addAllToVector(relatedNodes, ownedNodes);
}
}
public void setDiscoveryTime(int time) {
discoveryTime = time;
}
public void setFinishingTime(int time) {
finishingTime = time;
}
public void setPredecessor(CommitOrderDependencyNode n) {
predecessor = n;
}
public String toString() {
if (descriptor == null) {
return ToStringLocalization.buildMessage("empty_commit_order_dependency_node", (Object[])null);
} else {
Object[] args = { descriptor };
return ToStringLocalization.buildMessage("node", args);
}
}
public void visit() {
//Visit this node as part of a topological sort
int startTime;
markInProgress();
startTime = getOwner().getNextTime();
setDiscoveryTime(startTime);
for (Enumeration e = getRelatedNodes().elements(); e.hasMoreElements();) {
CommitOrderDependencyNode node = (CommitOrderDependencyNode)e.nextElement();
if (node.hasNotBeenVisited()) {
node.setPredecessor(this);
node.visit();
}
if (node.getPredecessor() == null) {
node.setPredecessor(this);
}
}
markVisited();
setFinishingTime(getOwner().getNextTime());
}
// Return an enumeration of all mappings for my descriptor, including those inherited
public Vector withAllSubclasses(CommitOrderDependencyNode node) {
Vector results = new Vector();
results.addElement(node);
if (node.getDescriptor().hasInheritance()) {
InheritancePolicy policy = node.getDescriptor().getInheritancePolicy();
// For bug 3019934 replace getChildDescriptors with getAllChildDescriptors.
List childDescriptors = new ArrayList();
childDescriptors.addAll(policy.getAllChildDescriptors());
// Sort Child Descriptors before adding them to related nodes.
Collections.sort(childDescriptors, new DescriptorCompare());
for (ClassDescriptor child : childDescriptors) {
results.add(getOwner().nodeFor(child));
}
}
return results;
}
}