blob: d236159f42a0a53a0f861c0c12660ae873408e99 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2013 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.queries;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.internal.expressions.FunctionExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
/**
* <b>Purpose</b>: represents an item requested (i.e. field for SELECT)
*
* @author Doug Clarke
* @since 2.0
*/
public class ReportItem implements Cloneable, java.io.Serializable {
/** Expression (partial) describing the attribute wanted */
protected Expression attributeExpression;
/** Name given for item, can be used to retrieve value from result. Useful if same field retrieved multiple times */
protected String name;
/** Mapping which relates field to attribute, used to convert value and determine reference descriptor */
protected DatabaseMapping mapping;
/** Descriptor for object result that is not based on an expression */
protected ClassDescriptor descriptor;
/** Result type for this report item. */
protected Class resultType;
/** Stores the Join information for this item */
protected JoinedAttributeManager joinedAttributeManager;
/** Stores the row index for this item, given multiple results and joins */
protected int resultIndex;
public ReportItem() {
super();
}
public ReportItem(String name, Expression attributeExpression) {
this();
this.name = name;
this.attributeExpression = attributeExpression;
}
public Object clone(){
try{
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
public Expression getAttributeExpression() {
return attributeExpression;
}
public void setAttributeExpression(Expression attributeExpression) {
this.attributeExpression = attributeExpression;
}
public ClassDescriptor getDescriptor(){
return this.descriptor;
}
/**
* INTERNAL:
* Set the list of expressions that represent elements that are joined because of their
* mapping for this query.
*/
public JoinedAttributeManager getJoinedAttributeManager() {
if (this.joinedAttributeManager == null) {
this.joinedAttributeManager = new JoinedAttributeManager();
}
return this.joinedAttributeManager;
}
public JoinedAttributeManager getJoinedAttributeManagerInternal(){
return joinedAttributeManager;
}
/**
* INTERNAL:
* Return if any attributes are joined.
* To avoid the initialization of the JoinedAttributeManager this should be first checked before accessing.
*/
public boolean hasJoining() {
return this.joinedAttributeManager != null;
}
public DatabaseMapping getMapping() {
return mapping;
}
public String getName() {
return name;
}
public int getResultIndex() {
return resultIndex;
}
public Class getResultType() {
return resultType;
}
/**
* INTERNAL:
* Looks up mapping for attribute during preExecute of ReportQuery
*/
public void initialize(ReportQuery query) throws QueryException {
if (this.mapping == null) {
if (this.attributeExpression != null) {
DatabaseMapping mapping = this.attributeExpression.getLeafMapping(query, query.getDescriptor(), query.getSession());
if (mapping == null && this.attributeExpression.isFunctionExpression() && this.getResultType() == null){
FunctionExpression expression = ((FunctionExpression)this.attributeExpression);
if (expression.getOperator().equals(ExpressionOperator.maximum()) || expression.getOperator().equals(ExpressionOperator.minimum())){
mapping = expression.getBaseExpression().getLeafMapping(query, query.getDescriptor(), query.getSession());
}
}
if (mapping == null){
if (this.attributeExpression.isExpressionBuilder()) {
Class resultClass = ((ExpressionBuilder)this.attributeExpression).getQueryClass();
if (resultClass == null){
resultClass = query.getReferenceClass();
((ExpressionBuilder)this.attributeExpression).setQueryClass(resultClass);
}
setDescriptor(query.getSession().getDescriptor(resultClass));
if (getDescriptor().hasInheritance()){
((ExpressionBuilder)this.attributeExpression).setShouldUseOuterJoinForMultitableInheritance(true);
}
}
} else {
if (mapping.isAbstractDirectMapping() || this.attributeExpression.isMapEntryExpression() || mapping.isAggregateObjectMapping() || mapping.isDirectCollectionMapping()){
setMapping(mapping);
//Bug4942640 Widen the check to support collection mapping too
} else if (mapping.isForeignReferenceMapping()) {
// DirectCollectionMapping doesn't have reference descriptor
if(mapping.getReferenceDescriptor() != null) {
setDescriptor(mapping.getReferenceDescriptor());
if (getDescriptor().hasInheritance()){
((QueryKeyExpression)this.attributeExpression).setShouldUseOuterJoinForMultitableInheritance(true);
}
}
} else {
throw QueryException.invalidExpressionForQueryItem(this.attributeExpression, query);
}
}
if (hasJoining()) {
this.joinedAttributeManager.setDescriptor(this.descriptor);
this.joinedAttributeManager.setBaseQuery(query);
}
if (getAttributeExpression() != null){
if (getAttributeExpression().getBuilder().wasQueryClassSetInternally()){
//rebuild if class was not set by user this ensures the query has the same base
this.attributeExpression = this.attributeExpression.rebuildOn(query.getExpressionBuilder());
}
if (hasJoining()) {
this.joinedAttributeManager.setBaseExpressionBuilder(this.attributeExpression.getBuilder());
}
} else if (hasJoining()) {
this.joinedAttributeManager.setBaseExpressionBuilder(query.getExpressionBuilder());
}
if (hasJoining()) {
this.joinedAttributeManager.prepareJoinExpressions(query.getSession());
this.joinedAttributeManager.processJoinedMappings(query.getSession());
this.joinedAttributeManager.computeJoiningMappingQueries(query.getSession());
}
}
}
}
public boolean isConstructorItem(){
return false;
}
/**
* @return true if there is no expression (null)
*/
public boolean isPlaceHolder() {
return getAttributeExpression() == null;
}
public void setDescriptor(ClassDescriptor descriptor){
this.descriptor = descriptor;
}
public void setJoinedAttributeManager(JoinedAttributeManager joinManager){
this.joinedAttributeManager = joinManager;
}
public void setMapping(DatabaseMapping mapping) {
this.mapping = mapping;
}
public void setResultIndex(int resultIndex) {
this.resultIndex = resultIndex;
if (hasJoining()) {
getJoinedAttributeManager().setParentResultIndex(resultIndex);
}
}
public void setResultType(Class resultType) {
this.resultType = resultType;
// Set it on the attribute expression as well if it is a function.
if (getAttributeExpression()!=null && getAttributeExpression().isFunctionExpression()) {
((FunctionExpression) getAttributeExpression()).setResultType(resultType);
}
}
public String toString() {
return "ReportQueryItem(" + getName() + " -> " + getAttributeExpression() + ")";
}
}