FileDocCategorySizeDatePackage
ExpressionBuilder.javaAPI DocGlassfish v2 API16371Tue May 22 16:54:20 BST 2007oracle.toplink.essentials.expressions

ExpressionBuilder

public class ExpressionBuilder extends ObjectExpression

Purpose: Allow for instances of expression to be created. Expressions are Java object-level representations of SQL "where" clauses. The expressions attempt to mirror Java code as closely as possible.

Example:

ExpressionBuilder employee = new ExpressionBuilder(); employee.get("firstName").equal("Bob").and(employee.get("lastName").equal("Smith")) >> equivalent Java code: (employee.getFirstName().equals("Bob")) && (employee.getLastName().equals("Smith")) >> equivalent SQL: (F_NAME = 'Bob') AND (L_NAME = 'Smith')
see
Expression

Fields Summary
protected transient AbstractSession
session
protected Class
queryClass
protected SQLSelectStatement
statement
protected DatabaseTable
viewTable
protected DatabaseTable
aliasedViewTable
protected boolean
wasQueryClassSetInternally
protected boolean
wasAdditionJoinCriteriaUsed
Constructors Summary
public ExpressionBuilder()
PUBLIC: Create a new ExpressionBuilder.


              
      
        super();
    
public ExpressionBuilder(Class queryClass)
ADVANCED: Create a new ExpressionBuilder representing instances of the argument class. This can be used for the purpose of parallel expressions. This is a type of query that searches on the relationship between to un-related objects.

        super();
        this.queryClass = queryClass;
        this.wasQueryClassSetInternally = false;
    
Methods Summary
public oracle.toplink.essentials.internal.helper.DatabaseTablealiasForTable(oracle.toplink.essentials.internal.helper.DatabaseTable table)
INTERNAL: Find the alias for a given table. Handle the special case where we are bogus and it should be aliased against our derived tables instead.

        if (hasViewTable()) {
            return getAliasedViewTable();
        }

        if (doesNotRepresentAnObjectInTheQuery()) {
            for (Enumeration e = derivedTables.elements(); e.hasMoreElements();) {
                TableExpression t = (TableExpression)e.nextElement();
                DatabaseTable result = t.aliasForTable(table);
                if (result != null) {
                    return result;
                }
            }
        } else {
            return super.aliasForTable(table);
        }
        return null;// No alias found in the derived tables
    
public intassignTableAliasesStartingAt(int initialValue)
INTERNAL: Assign aliases to any tables which I own. Start with t, and return the new value of the counter , i.e. if initialValue is one and I have tables ADDRESS and EMPLOYEE I will assign them t1 and t2 respectively, and return 3.

        if (hasBeenAliased()) {
            return initialValue;
        }

        if (doesNotRepresentAnObjectInTheQuery()) {
            return initialValue;
        }

        // This block should be removed I think.
        // The only reason to clone might be to
        // preserve the qualifier, but aliases need
        // qualifiers?  That seems strange.
        // Also this will break AsOf queries.  By
        // inference if has view table the AliasTableLookup
        // will contain one table, and that will be the
        // table of the view...
        if (hasViewTable()) {
            DatabaseTable aliased = (DatabaseTable)viewTable.clone();
            String alias = "t" + initialValue;
            aliased.setName(alias);
            assignAlias(alias, viewTable);
            aliasedViewTable = aliased;
            return initialValue + 1;
        }
        return super.assignTableAliasesStartingAt(initialValue);
    
public java.lang.StringdescriptionOfNodeType()
INTERNAL: Used for debug printing.

        return "Base";
    
public booleandoesNotRepresentAnObjectInTheQuery()
INTERNAL: There are cases (which we might want to eliminate?) where the expression builder doesn't actually correspond to an object to be read. Mostly this is the case where it's a data query in terms of tables, and the builder is only there to provide a base. It might be better to make tables able to serve as their own base, but it's very nice to have a known unique, shared base. In the meantime, this is a special case to make sure the builder doesn't get tables assigned.

        return (hasDerivedTables() && !hasDerivedFields() && !hasDerivedExpressions());
    
public oracle.toplink.essentials.internal.helper.DatabaseTablegetAliasedViewTable()
INTERNAL:

        return aliasedViewTable;

    
public oracle.toplink.essentials.expressions.ExpressionBuildergetBuilder()
INTERNAL: Return the expression builder which is the ultimate base of this expression, or null if there isn't one (shouldn't happen if we start from a root)

        return this;
    
public oracle.toplink.essentials.descriptors.ClassDescriptorgetDescriptor()
INTERNAL: Only usable after the session and class have been set. Return the descriptor for the class this node represents.

        if (descriptor == null) {
            if (getQueryClass() == null) {
                return null;
            } else {
                if (getSession() == null) {
                    throw QueryException.noExpressionBuilderFound(this);
                }
                descriptor = getSession().getDescriptor(getQueryClass());
            }
        }
        return descriptor;

    
public java.lang.ClassgetQueryClass()
INTERNAL:

        return queryClass;
    
public oracle.toplink.essentials.internal.sessions.AbstractSessiongetSession()
INTERNAL:

        return session;
    
public oracle.toplink.essentials.internal.expressions.SQLSelectStatementgetStatement()
INTERNAL: Return the statement that expression is for. This is used for the context in subselects.

        return statement;
    
public oracle.toplink.essentials.internal.helper.DatabaseTablegetViewTable()
INTERNAL:

        return viewTable;
    
public booleanhasViewTable()
INTERNAL:

        return viewTable != null;
    
public booleanisExpressionBuilder()
INTERNAL:

        return true;
    
public oracle.toplink.essentials.expressions.Expressionnormalize(oracle.toplink.essentials.internal.expressions.ExpressionNormalizer normalizer)
INTERNAL: Normalize the expression into a printable structure. Any joins must be added to form a new root.

        if (hasBeenNormalized()) {
            return this;
        } else {
            setHasBeenNormalized(true);
        }

        // This is required for parralel selects,
        // the session must be set and the addtional join expression added.
        if (this.queryClass != null) {
            Expression criteria = null;

            setSession(normalizer.getSession().getRootSession(null));
            // The descriptor must be defined at this point.
            if (getDescriptor() == null) {
                throw QueryException.noExpressionBuilderFound(this);
            }
            if (!this.wasAdditionJoinCriteriaUsed) {
                criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression();
                if (criteria != null) {
                    criteria = twist(criteria, this);
                }
            }

            if (isUsingOuterJoinForMultitableInheritance() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
                Expression childrenCriteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
                childrenCriteria = this.twist(childrenCriteria, this);
                childrenCriteria.convertToUseOuterJoin();
                if(criteria == null) {
                    criteria = childrenCriteria;
                } else {
                    criteria = criteria.and(childrenCriteria);
                }
            }
            if (isUsingOuterJoinForMultitableInheritance() && (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause())) {
                normalizer.getStatement().getOuterJoinExpressions().addElement(null);
                normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(null);
                normalizer.getStatement().getOuterJoinedAdditionalJoinCriteria().addElement(additionalExpressionCriteriaMap());
                normalizer.getStatement().getDescriptorsForMultitableInheritanceOnly().add(this.getDescriptor());
                // fall through to the main case
            }
            normalizer.addAdditionalExpression(criteria);


        }
        setStatement(normalizer.getStatement());
        

        return super.normalize(normalizer);
    
public voidprintJava(oracle.toplink.essentials.internal.expressions.ExpressionJavaPrinter printer)
INTERNAL: Print java

        printer.printString(printer.getBuilderString());        
    
public oracle.toplink.essentials.expressions.ExpressionrebuildOn(oracle.toplink.essentials.expressions.Expression newBase)
INTERNAL: This expression is built on a different base than the one we want. Rebuild it and return the root of the new tree This assumes that the original expression has only a single builder.

        return newBase;
    
protected oracle.toplink.essentials.expressions.ExpressionregisterIn(java.util.Dictionary alreadyDone)
INTERNAL: Override Expression.registerIn to check if the new base expression has already been provided for the clone.

see
oracle.toplink.essentials.expressions.Expression#cloneUsing(Expression)
bug
2637484 INVALID QUERY KEY EXCEPTION THROWN USING BATCH READS AND PARALLEL EXPRESSIONS

        // Here do a special check to see if this a cloneUsing(newBase) call.
        Object value = alreadyDone.get(alreadyDone);
        if ((value == null) || (value == alreadyDone)) {
            // This is a normal cloning operation.
            return super.registerIn(alreadyDone);
        }
        ObjectExpression copy = (ObjectExpression)value;

        // copy is actually the newBase of a cloneUsing.
        alreadyDone.put(alreadyDone, alreadyDone);
        alreadyDone.put(this, copy);
        // Now need to copy over the derived expressions, etc.
        if (this.derivedExpressions != null) {
            if (copy.derivedExpressions == null) {
                copy.derivedExpressions = copyCollection(this.derivedExpressions, alreadyDone);
            } else {
                copy.derivedExpressions.addAll(copyCollection(this.derivedExpressions, alreadyDone));
            }
        }

        // Do the same for these protected fields.
        copy.postCopyIn(alreadyDone, this.derivedFields, this.derivedTables);
        return copy;
    
public voidsetQueryClass(java.lang.Class queryClass)
INTERNAL: Set the class which this node represents.

        this.queryClass = queryClass;
        this.descriptor = null;
    
public voidsetSession(oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Set the session in which we expect this expression to be translated.

        this.session = session;
    
public voidsetStatement(oracle.toplink.essentials.internal.expressions.SQLSelectStatement statement)
INTERNAL: Set the statement that expression is for. This is used for the context in subselects.

        this.statement = statement;
    
public voidsetViewTable(oracle.toplink.essentials.internal.helper.DatabaseTable theTable)
INTERNAL: This expression represents something read through a view table.

        viewTable = theTable;

    
public voidsetWasAdditionJoinCriteriaUsed(boolean joinCriteriaUsed)
INTERNAL: If the additional Join Criteria for the class this builder represents has been added to the statement then mark this as true. This will prevent TopLink from adding it again at normalization

        this.wasAdditionJoinCriteriaUsed = joinCriteriaUsed;
    
public oracle.toplink.essentials.expressions.ExpressiontwistedForBaseAndContext(oracle.toplink.essentials.expressions.Expression newBase, oracle.toplink.essentials.expressions.Expression context)
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"

param
newBase
param
context
return

        return newBase;
    
public java.lang.ObjectvalueFromObject(java.lang.Object object, oracle.toplink.essentials.internal.sessions.AbstractSession session, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.queryframework.InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered)
INTERNAL: The expression builder represent the entire object, just return it.

        return object;
    
public booleanwasAdditionJoinCriteriaUsed()
INTERNAL: If the additional Join Criteria for the class this builder represents has been added to the statement this method will return true;

        return this.wasAdditionJoinCriteriaUsed;
    
public booleanwasQueryClassSetInternally()
INTERNAL: Returns true if TopLink set the query class as appoased to the customer. This is important in determining if this Expression should be treated as a parallel expression during normalization

        return this.wasQueryClassSetInternally;
    
public voidwriteDescriptionOn(java.io.BufferedWriter writer)
INTERNAL: For debug printing purposes.

        String className;
        if (getQueryClass() == null) {
            className = "QUERY OBJECT";
        } else {
            className = getQueryClass().getName();
        }
        writer.write(className + tableAliasesDescription());