/******************************************************************************* * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.expressions; import java.util.*; import org.eclipse.persistence.internal.helper.DatabaseTable; import org.eclipse.persistence.mappings.querykeys.*; import org.eclipse.persistence.expressions.*; import org.eclipse.persistence.descriptors.ClassDescriptor; /** * This class represents a "query key" that isn't really there * in the descriptors. For example, I could use this to create * an 'employee' query key from an 'address' node even if addresses * don't know their employee. It's called manual, because I will * have to provide the relevant join criteria myself (normally based * on a reverse relationship. Motivated by batch reading. */ public class ManualQueryKeyExpression extends QueryKeyExpression { public ManualQueryKeyExpression() { super(); } public ManualQueryKeyExpression(String impliedRelationshipName, Expression base) { super(impliedRelationshipName, base); } public ManualQueryKeyExpression(String impliedRelationshipName, Expression base, ClassDescriptor descriptor) { super(impliedRelationshipName, base); this.descriptor = descriptor; } /** * INTERNAL: * Return if the expression is equal to the other. * This is used to allow dynamic expression's SQL to be cached. */ public boolean equals(Object object) { if (this == object) { return true; } // Equality cannot easily be determined for maunal expressions. return false; } /** * INTERNAL: * Used for debug printing. */ public String descriptionOfNodeType() { return "Manual Query Key"; } /** * INTERNAL: * If we ever get in the circumstance of a manual query key * to an aggregate, then we can assume that the owner of that * aggregate isn't participating (and even if it is, we can't * know which node it is, so *DO* use the aggregate's parents tables */ public List<DatabaseTable> getOwnedTables() { if (getDescriptor() == null) { return null; } else { if ((getDescriptor().getHistoryPolicy() != null) && (getAsOfClause().getValue() != null)) { return getDescriptor().getHistoryPolicy().getHistoricalTables(); } return getDescriptor().getTables(); } } public QueryKey getQueryKeyOrNull() { return null; } /** * INTERNAL: * We can never be an attribute, we're always a join */ public boolean isAttribute() { return false; } @Override public Expression mappingCriteria(Expression base) { return null; } /** * INTERNAL: * This expression is built on a different base than the one we want. Rebuild it and * return the root of the new tree */ public Expression rebuildOn(Expression newBase) { ObjectExpression newLocalBase = (ObjectExpression)getBaseExpression().rebuildOn(newBase); return newLocalBase.getManualQueryKey(getName(), getDescriptor()); } /** * INTERNAL: * Rebuild myself against the base, with the values of parameters supplied by the context * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping) * into part of some larger expression. You normally would not call this directly, instead calling twist * See the comment there for more details" */ @Override public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) { ObjectExpression twistedBase = (ObjectExpression)getBaseExpression().twistedForBaseAndContext(newBase, context, oldBase); return twistedBase.getManualQueryKey(getName(), getDescriptor()); } /** * Do any required validation for this node. Throw an exception if it's incorrect. */ public void validateNode() { // Override super.validateNode() because those criteria don't apply to us } }