org.eclipse.persistence.internal.jpa.parsing.AttributeNode 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, 2020 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.jpa.parsing;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.JPQLException;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
/**
* INTERNAL
* Purpose: Represent a attribute.
*
*
Responsibilities:
*
*/
public class AttributeNode extends Node {
/** The attribute name. */
private String name;
/** Flag indicating outer join */
private boolean outerJoin;
/** */
private boolean requiresCollectionAttribute;
/** */
private DatabaseMapping mapping;
private String castClassName = null;
private QueryKey attributeQueryKey = null;
/**
* Create a new AttributeNode
*/
public AttributeNode() {
super();
}
/**
* Create a new AttributeNode with the passed name
* @param name the attribute name
*/
public AttributeNode(String name) {
setAttributeName(name);
}
/**
* INTERNAL
* If called this AttributeNode represents an unqualified field access.
* The method returns a DotNode representing a qualified field access with
* the base variable as left child node and the attribute as right child
* node.
*/
@Override
public Node qualifyAttributeAccess(ParseTreeContext context) {
return (Node)context.getNodeFactory().newQualifiedAttribute(
getLine(), getColumn(), context.getBaseVariable(), name);
}
/**
* INTERNAL
* Validate the current node and calculates its type.
*/
@Override
public void validate(ParseTreeContext context) {
// The type is calculated in the parent DotNode.
}
public Expression appendCast(Expression exp, GenerationContext context){
if (castClassName == null){
return exp;
}
TypeHelper typeHelper = context.getParseTreeContext().getTypeHelper();
Class cast = (Class)typeHelper.resolveSchema(castClassName);
return exp.treat(cast);
}
public Object computeActualType(Object initialType, TypeHelper typeHelper){
if (castClassName != null){
return typeHelper.resolveSchema(castClassName);
}
return initialType;
}
public void checkForQueryKey(Object ownerType, TypeHelper typeHelper){
attributeQueryKey = typeHelper.resolveQueryKey(ownerType, name);
}
/** */
@Override
public Expression addToExpression(Expression parentExpression, GenerationContext context) {
if (isCollectionAttribute()) {
//special case for NOT MEMBER OF
if (context.hasMemberOfNode()) {
return parentExpression.noneOf(name, new ExpressionBuilder().equal(context.getMemberOfNode().getLeftExpression()));
}
return outerJoin ? appendCast(parentExpression.anyOfAllowingNone(name), context) :
appendCast(parentExpression.anyOf(name), context);
} else {
// check whether collection attribute is required
if (requiresCollectionAttribute()) {
throw JPQLException.invalidCollectionMemberDecl(
context.getParseTreeContext().getQueryInfo(),
getLine(), getColumn(), name);
}
if (context.shouldUseOuterJoins() || isOuterJoin()) {
return appendCast(parentExpression.getAllowingNull(name), context);
} else {
return appendCast(parentExpression.get(name), context);
}
}
}
/**
* INTERNAL
* Is this node an AttributeNode
*/
@Override
public boolean isAttributeNode() {
return true;
}
/** */
public String getAttributeName() {
return name;
}
/** */
public void setAttributeName(String name) {
this.name = name;
}
public String getCastClassName() {
return castClassName;
}
public void setCastClassName(String castClassName) {
this.castClassName = castClassName;
}
/** */
public boolean isOuterJoin() {
return outerJoin;
}
/** */
public void setOuterJoin(boolean outerJoin) {
this.outerJoin = outerJoin;
}
/** */
public boolean requiresCollectionAttribute() {
return requiresCollectionAttribute;
}
/** */
public void setRequiresCollectionAttribute(boolean requiresCollectionAttribute) {
this.requiresCollectionAttribute = requiresCollectionAttribute;
}
/** */
public DatabaseMapping getMapping() {
return mapping;
}
/** */
public void setMapping(DatabaseMapping mapping) {
this.mapping = mapping;
}
/** */
public boolean isCollectionAttribute() {
DatabaseMapping mapping = getMapping();
return ((mapping != null) && mapping.isCollectionMapping()) || (attributeQueryKey != null && attributeQueryKey.isCollectionQueryKey());
}
/**
* resolveMapping: Answer the mapping which corresponds to my variableName.
*/
@Override
public DatabaseMapping resolveMapping(GenerationContext context, Class ownerClass) {
ClassDescriptor descriptor = context.getSession().getDescriptor(ownerClass);
return (descriptor==null) ? null : descriptor.getObjectBuilder().getMappingForAttributeName(getAttributeName());
}
/**
* resolveClass: Answer the class for the mapping associated with the my variableName in the ownerClass.
* Answer null if the node represents a mapping that doesn't exist
*/
@Override
public Class resolveClass(GenerationContext context, Class ownerClass) {
DatabaseMapping mapping;
mapping = resolveMapping(context, ownerClass);
// if we are working with a direct-to-field, or the mapping's null,
// return the owner class
// Returning the ownerClass when the mapping is null delegates error handling
// to the query rather than me
if ((mapping == null) || (mapping.isDirectToFieldMapping())) {
return ownerClass;
}
ClassDescriptor descriptor = mapping.getReferenceDescriptor();
return (descriptor==null) ? null : descriptor.getJavaClass();
//return mapping.getReferenceDescriptor().getJavaClass();
}
@Override
public String toString(int indent) {
StringBuilder buffer = new StringBuilder();
toStringIndent(indent, buffer);
buffer.append(toStringDisplayName() + "[" + getAttributeName() + "]");
return buffer.toString();
}
/**
* INTERNAL
* Get the string representation of this node.
*/
@Override
public String getAsString() {
return getAttributeName();
}
}