Package Express.services

Source Code of Express.services.BusinessQuery

package Express.services;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.util.Iterator;

import DisplayProject.binding.beans.ExtendedPropertyChangeSupport;
import DisplayProject.binding.beans.Observable;
import Framework.Array_Of_IntegerData;
import Framework.Array_Of_Object;
import Framework.Array_Of_TextData;
import Framework.CloneHelper;
import Framework.DataValue;
import Framework.DateFormat;
import Framework.DateTimeData;
import Framework.DecimalData;
import Framework.DoubleData;
import Framework.IntegerData;
import Framework.NumericData;
import Framework.NumericFormat;
import Framework.ParameterHolder_TextData;
import Framework.ParameterHolder_integer;
import Framework.RuntimeProperties;
import Framework.TextData;
import Framework.TextFormat;
import Framework.TextFormat.qq_Resolver;
import GenericDBMS.DBConnectionManager;
import GenericDBMS.DBDataSet;

/**
* BusinessQuery is the base class for all generated and custom query classes. Express generates subclasses of the BusinessQuery class for each business class.
* <p>
* @author ITerative Consulting
* @since  26-Feb-2008
*/
@RuntimeProperties(isDistributed=false, isAnchored=false, isShared=false, isTransactional=false)
@SuppressWarnings("serial")
public class BusinessQuery
        implements Serializable, Observable
{

    // ---------
    // Constants
    // ---------
    public static final int ASSOC_AGGREGATION = 64;
    public static final int ASSOC_MULT_MANY_TO = 2;
    public static final int ASSOC_MULT_ONE_MASK = 20;
    public static final int ASSOC_MULT_ONE_TO = 1;
    public static final int ASSOC_MULT_OPTIONAL = 16;
    public static final int ASSOC_MULT_TO_MANY = 8;
    public static final int ASSOC_MULT_TO_ONE = 4;
    public static final int ATTR_DB = -2;
    public static final int ATTR_FOREIGN = 10000;
    public static final int ATTR_KEY = -1;
    public static final int ATTR_SIMPLE = 0;
    public static final int OP_DELETE = 1;
    public static final int OP_INSERT = 2;
    public static final int OP_NONE = 0;
    public static final int OP_SELECT = 3;
    public static final int OP_UPDATE = 4;
    public static final int QUERY_INFO_BUILT = 1;
    public static final int QUERY_INFO_EXECUTED = 2;
    public static final int QUERY_INFO_JOINED = 4;

    // ----------
    // Attributes
    // ----------
    public PropertyChangeSupport qq_Listeners = new ExtendedPropertyChangeSupport(this, true);
    private QueryConstraint constraint;
    private Array_Of_BusinessQuery<BusinessQuery> foreignClasses;
    private BusinessKey key;
    private int operation;
    private BusinessClass originalClass;
    private int parentAttr;
    private int parentMult;
    private Array_Of_IntegerData<IntegerData> tableAliases;
    private Array_Of_IntegerData<IntegerData> targetAttrs;
    private BusinessClass updatedClass;
    private QueryConstraint values;
    // AD:25/11/2008: Do not pass exectueInfo across VM boundaries. Contains non serializable classes
    private transient QueryExecuteInfo _ExecuteInfo;

    // ------------
    // Constructors
    // ------------
    public BusinessQuery() {
        // Explicitly call the superclass constructor to prevent the implicit call
        super();

        this.operation = BusinessQuery.OP_SELECT;

    }

    // ----------------------
    // Accessors and Mutators
    // ----------------------
    public void setConstraint(QueryConstraint constraint) {
        QueryConstraint oldValue = this.constraint;
        this.constraint = constraint;
        this.qq_Listeners.firePropertyChange("constraint", oldValue, this.constraint);
    }

    public QueryConstraint getConstraint() {
        return this.constraint;
    }

    public void setForeignClasses(Array_Of_BusinessQuery<BusinessQuery> foreignClasses) {
        Array_Of_BusinessQuery<BusinessQuery> oldValue = this.foreignClasses;
        this.foreignClasses = foreignClasses;
        this.qq_Listeners.firePropertyChange("foreignClasses", oldValue, this.foreignClasses);
    }

    public Array_Of_BusinessQuery<BusinessQuery> getForeignClasses() {
        return this.foreignClasses;
    }

    public void setKey(BusinessKey key) {
        BusinessKey oldValue = this.key;
        this.key = key;
        this.qq_Listeners.firePropertyChange("key", oldValue, this.key);
    }

    public BusinessKey getKey() {
        return this.key;
    }

//    private void setOperation(int operation) {
//        int oldValue = this.operation;
//        this.operation = operation;
//        this.qq_Listeners.firePropertyChange("operation", oldValue, this.operation);
//    }

    public int getOperation() {
        return this.operation;
    }

    public void setOriginalClass(BusinessClass originalClass) {
        BusinessClass oldValue = this.originalClass;
        this.originalClass = originalClass;
        this.qq_Listeners.firePropertyChange("originalClass", oldValue, this.originalClass);
    }

    public BusinessClass getOriginalClass() {
        return this.originalClass;
    }

    public void setParentAttr(int parentAttr) {
        int oldValue = this.parentAttr;
        this.parentAttr = parentAttr;
        this.qq_Listeners.firePropertyChange("parentAttr", oldValue, this.parentAttr);
    }

    public int getParentAttr() {
        return this.parentAttr;
    }

    public void setParentMult(int parentMult) {
        int oldValue = this.parentMult;
        this.parentMult = parentMult;
        this.qq_Listeners.firePropertyChange("parentMult", oldValue, this.parentMult);
    }

    public int getParentMult() {
        return this.parentMult;
    }

    public void setTableAliases(Array_Of_IntegerData<IntegerData> tableAliases) {
        Array_Of_IntegerData<IntegerData> oldValue = this.tableAliases;
        this.tableAliases = tableAliases;
        this.qq_Listeners.firePropertyChange("tableAliases", oldValue, this.tableAliases);
    }

    public Array_Of_IntegerData<IntegerData> getTableAliases() {
        return this.tableAliases;
    }

    public void setTargetAttrs(Array_Of_IntegerData<IntegerData> targetAttrs) {
        Array_Of_IntegerData<IntegerData> oldValue = this.targetAttrs;
        this.targetAttrs = targetAttrs;
        this.qq_Listeners.firePropertyChange("targetAttrs", oldValue, this.targetAttrs);
    }

    public Array_Of_IntegerData<IntegerData> getTargetAttrs() {
        return this.targetAttrs;
    }

    public void setUpdatedClass(BusinessClass updatedClass) {
        BusinessClass oldValue = this.updatedClass;
        this.updatedClass = updatedClass;
        this.qq_Listeners.firePropertyChange("updatedClass", oldValue, this.updatedClass);
    }

    public BusinessClass getUpdatedClass() {
        return this.updatedClass;
    }

    public void setValues(QueryConstraint values) {
        QueryConstraint oldValue = this.values;
        this.values = values;
        this.qq_Listeners.firePropertyChange("values", oldValue, this.values);
    }

    public QueryConstraint getValues() {
        return this.values;
    }

    @SuppressWarnings("unused")
  private void set_ExecuteInfo(QueryExecuteInfo _ExecuteInfo) {
        QueryExecuteInfo oldValue = this._ExecuteInfo;
        this._ExecuteInfo = _ExecuteInfo;
        this.qq_Listeners.firePropertyChange("_ExecuteInfo", oldValue, this._ExecuteInfo);
    }

    @SuppressWarnings("unused")
  private QueryExecuteInfo get_ExecuteInfo() {
        return this._ExecuteInfo;
    }

    // ------------------
    // Virtual attributes
    // ------------------
    // -------------------------------------------------
    // (Virtual) Attribute NumAttrs
    // -------------------------------------------------
    public int getNumAttrs() {
        return this.getNumAttrs(0);
    }

    // -------------------------------------------------
    // (Virtual) Attribute NumDBAttrs
    // -------------------------------------------------
    public int getNumDBAttrs() {
        int numDBAttrs = 0;
        numDBAttrs = this.getNumAttrs(BusinessQuery.ATTR_DB);
        return numDBAttrs;
    }

    // -------------------------------------------------
    // (Virtual) Attribute NumForeignAttrs
    // -------------------------------------------------
    public int getNumForeignAttrs() {
        int numForeignAttrs = 0;
        numForeignAttrs = this.getNumAttrs(BusinessQuery.ATTR_FOREIGN);
        return numForeignAttrs;
    }

    // -------------------------------------------------
    // (Virtual) Attribute NumKeyAttrs
    // -------------------------------------------------
    public int getNumKeyAttrs() {
        int numKeyAttrs = 0;
        numKeyAttrs = this.getNumAttrs(BusinessQuery.ATTR_KEY);
        return numKeyAttrs;
    }

    // -------------------------------------------------
    // (Virtual) Attribute NumTables
    // -------------------------------------------------
    public int getNumTables() {
        return this.qq_getNumTables();
    }

    // -------------------------------------------------
    // (Virtual) Attribute ExecuteInfo
    // -------------------------------------------------
    public QueryExecuteInfo getExecuteInfo() {
        return this.qq_getExecuteInfo();
    }

    // -------
    // Methods
    // -------
    public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
        qq_Listeners.addPropertyChangeListener(property, listener);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        qq_Listeners.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(String property, PropertyChangeListener listener) {
        qq_Listeners.removePropertyChangeListener(property, listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        qq_Listeners.removePropertyChangeListener(listener);
    }

    /**
     * addAttr<p>
     * AddAttr<br>
     *     The AddAttr method is used to specify which attributes should be<br>
     *     returned in a BusinessClass.  The columns in the database corresponding<br>
     *     to these attributes will be selected from the database and their values<br>
     *     used as the values of the attributes requested.  If the attribute<br>
     *     requested is a dependent or foreign entity then a BusinessQuery must<br>
     *     be provided which describes which attributes of the dependent or foreign<br>
     *     entity should be returned and, optionally, constraints on the entity.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index which specifies an<br>
     *       attribute which should be returned.  Attribute indexes common to<br>
     *       all BusinessQueries and BusinessEntities are defined in<br>
     *       BusinessQuery.  These are ATTR_SIMPLE, ATTR_FOREIGN, and<br>
     *       ATTR_KEY.  Attribute indexes particular to a given<br>
     *       BusinessQuery or BusinessClass are defined in that entity's<br>
     *       generated query class and prefixed by ATTR_.<br>
     * <p>
     *     query<br>
     *       The query parameter specifies a BusinessQuery describing attributes<br>
     *       and constraints for a foreign or dependent entity.<br>
     * <p>
     * @param attr Type: int
     * @param query Type: BusinessQuery (Input) (default in Forte: NIL)
     */
    public void addAttr(int attr, BusinessQuery query) {
        if (attr < BusinessQuery.ATTR_FOREIGN) {

            //
            //  It is a simple attribute, just add it to the TargetAttrs array.
            //

            if (this.getTargetAttrs() == null) {
                this.setTargetAttrs(new Array_Of_IntegerData<IntegerData>());
            }

            if (attr != BusinessQuery.ATTR_SIMPLE) {

                if (attr > this.getNumAttrs()) {
                    throw new Error(Error.BQ_ILLEGAL_ATTR, "AddAttr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }
                else {
                    int row = (attr-1)/31+1;
                    double bit = (attr-1) % 31;
                    for (int i = this.getTargetAttrs().size()+1; i <= row; i++) {
                        this.getTargetAttrs().set(i-1, new IntegerData(0));
                    }
                    this.getTargetAttrs().get(row-1).setValue(this.getTargetAttrs().get(row-1).getValue()|((int)new DoubleData(2).power(bit).getValue()));
                }

            }
            else {
                //
                //  ATTR_SIMPLE means add all simple attributes
                //
                int attrs = 0;
                int numAtts = this.getNumAttrs();
                // virtual attr.
                while (attrs+31 < numAtts) {
                    attrs = attrs+31;
                    this.getTargetAttrs().set(attrs/31-1, new IntegerData(2147483647));
                }
                this.getTargetAttrs().set(attrs/31+1-1, new IntegerData((int)(new DoubleData(2).power(numAtts-attrs).getValue()-1)));

            }

        }
        else {

            //
            //  It is a foreign attribute.
            //

            if (query == null) {

                throw new Error(Error.BQ_NEED_QUERY, "AddAttr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
            else if (attr-BusinessQuery.ATTR_FOREIGN > this.getNumForeignAttrs()) {

                throw new Error(Error.BQ_ILLEGAL_ATTR, "AddAttr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
            else if (this.operation != BusinessQuery.OP_SELECT && query.operation == BusinessQuery.OP_SELECT) {

                throw new Error(Error.BQ_INCONSISTENT_OP, "AddAttr", this, new IntegerData(query.operation), new IntegerData(this.operation)).getException();
            }

            if (this.getForeignClasses() == null) {
                this.setForeignClasses(new Array_Of_BusinessQuery<BusinessQuery>());
            }
            else if ((this.operation == BusinessQuery.OP_SELECT) && (query.getTargetAttrs() != null)) {
                //
                //  Check and see if this foreign attribute is already specified.
                //  We do this for select queries which have TargetAttrs.  Select
                //  queries which don't have TargetAttrs are constraints only and
                //  they shouldn't be merged in as they are treated specially in the
                //  case of 1-to-many associations.  In that case they apply to the
                //  primary and not to the foreign query.
                //
                if (this.getForeignClasses() != null) {
                    for (BusinessQuery q : this.getForeignClasses()) {

                        if (q == query) {
                            //
                            //  It is already on the list, great! we don't need to do
                            //  anything.
                            //
                            return;

                        }
                        else if ((q.getParentAttr() == attr) && (q.getTargetAttrs() != null)) {

                            //
                            //  Bummer it has.  Now we need to merge the target lists and
                            //  constraints.  What fun.  We start with the target list.
                            //
                            int num = q.getTargetAttrs().size();
                            if (num > query.getTargetAttrs().size()) {
                                num = query.getTargetAttrs().size();
                            }
                            for (int i = 1; i <= num; i++) {
                                q.getTargetAttrs().get(i-1).setValue(q.getTargetAttrs().get(i-1).getValue()|query.getTargetAttrs().get(i-1).getValue());
                            }
                            for (int i = q.getTargetAttrs().size()+1; i <= query.getTargetAttrs().size(); i++) {
                                q.getTargetAttrs().add(query.getTargetAttrs().get(i-1));
                            }

                            //
                            //  Is there a constraint on the new query?
                            //
                            if (query.getConstraint() != null) {
                                //
                                //  Yep one of those too.
                                //
                                if (q.getConstraint() == null) {
                                    q.setConstraint(new QueryConstraint());
                                }
                                //
                                //  Now we have to fixup references on query's Constraint
                                //  stack to itself to point to q.
                                //
                                Array_Of_ConstraintNode<ConstraintNode> qq_localVector = query.getConstraint().getStack();
                                if (qq_localVector != null) {
                                    for (ConstraintNode c : qq_localVector) {
                                        if (c instanceof ConstraintAttr && ((ConstraintAttr)c).getEntity() == query) {
                                            ((ConstraintAttr)c).setEntity(q);
                                        }
                                    }
                                }
                                q.getConstraint().addConstraint(query.getConstraint());
                            }

                            //
                            //  Are there any foreign classes on the new query?
                            //
                            if (query.getForeignClasses() != null && query.getForeignClasses().size() > 0) {
                                //
                                //  Yep some of those too.
                                //
                                Array_Of_BusinessQuery<BusinessQuery> qq_localVector = query.getForeignClasses();
                                if (qq_localVector != null) {
                                    for (BusinessQuery fq : qq_localVector) {
                                        q.addAttr(fq.getParentAttr(), fq);
                                    }
                                }
                            }

                            //
                            //  Now that we've merged all the info from the new query into
                            //  the existing one we're done.
                            //
                            return;
                        }
                    }
                }
            }

            //
            //  Cache multiplicity info for the association between self and query
            //
            query.setParentMult(this.getForeignAttrMult(attr));

            //
            //  We attach this query to the ForeignClasses array and point it back
            //  to the proper attribute in this query.
            //
            query.setParentAttr(attr);
            this.getForeignClasses().add(query);

        }
    }
    /**
     * Same as {@link BusinessQuery#addAttr(int, BusinessQuery)} with the BisinessQuery defaulted to null.
     * @param attr
     */
    public void addAttr(int attr) {
      this.addAttr(attr, null);
    }
    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     This form of the AddConstraint method is used for constraints that<br>
     *     affect the whole query and are not specific to a particular attribute.<br>
     *     Examples are "order by" and max rows.<br>
     * <p>
     *     AddConstraint pushes the value (if any) and operation onto the<br>
     *     Constraint stack.<br>
     * <p>
     *     operation<br>
     *       The operation parameter specifies the relationship the attribute<br>
     *       should bear to the value.  Values for operation are defined in<br>
     *       the ConstraintOperation class.<br>
     * <p>
     *     value<br>
     *       The value parameter specifies the value to which the attribute<br>
     *       should be limited.<br>
     * <p>
     * @param operation Type: int
     * @param value Type: DataValue (Input) (default in Forte: NIL)
     */
    public void addConstraint(int operation, DataValue value) {
        if (this.getConstraint() == null) {
            this.setConstraint(new QueryConstraint());
        }

        if (value != null) {
            this.getConstraint().addValue(value);
        }
        else if (operation == ConstraintOperation.OP_MAX_ROWS) {
            throw new Error(Error.BQ_CONS_OP_NEEDS_VALUE, "AddConstraint", this).getException();
        }

        this.getConstraint().addOperation(operation);
    }
    public void addConstraint(int operation) {
      this.addConstraint(operation, null);
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method is used to limit the values of attributes for<br>
     *     BusinessEntities being selected.<br>
     * <p>
     *     AddConstraint pushes a value, attribute, and an operation onto the<br>
     *     Constraint stack.  The value parameter contains a text string with<br>
     *     an operation and a value.  The operation and value are parsed out and<br>
     *     used to build the constraint.  The type parameter determines what type<br>
     *     of operations can be parsed out and the datatype to which the value<br>
     *     parsed out of the value parameter will be cast.<br>
     * <p>
     *     If the type parameter is NIL or the value parameter is not a TextData<br>
     *     then the value parameter is used as the value and the operation '='<br>
     *     is used.<br>
     * <p>
     *     If the type parameter is a TextData then the value parameter is used<br>
     *     as the value and the operation is either '=', 'like', or 'is null'.<br>
     *     'like' is used if the value contains a '%' or '_' character.<br>
     *     The 'is null' operator is used if the value is 'NULL' (ignoring case).<br>
     * <p>
     *     If the type parameter is NumericData or DateTimeData then the value<br>
     *     parameter can be in the following forms:<br>
     * <p>
     *       [[not] <operator>] <value><br>
     *       [not] null<br>
     *       [not] between <value> and <value><br>
     *       [not] in (<value> [<value> ...])<br>
     * <p>
     *     where:<br>
     * <p>
     *       <operator>   ::= >= | <= | = | > | < | <NE><br>
     *       <NE>    ::= <> | != | ^=<br>
     *       <value>    ::= any string of characters not containing the<br>
     *               characters: ' ', '(', ')', '<', '>', '=',<br>
     *               '!', or '^'.<br>
     * <p>
     *     Any other form causes an exception to be raised.<br>
     * <p>
     *     The constraints on the stack are anded together by default.<br>
     *     More complex relationships on the Constraint stack are supported but<br>
     *     no interface is provided on BusinessQuery to construct them.  The<br>
     *     Constraint stack can be manipulated directly if necessary.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying an attribute<br>
     *       whose value should be limited.<br>
     * <p>
     *     value<br>
     *       The value parameter specifies the value to which the attribute<br>
     *       should be limited and depending on the type parameter may also<br>
     *       contain the operation.<br>
     * <p>
     *     type<br>
     *       The type parameter specifies to what datatype the value parameter<br>
     *       should be cast and how the value should be parsed.<br>
     * <p>
     *     templateText<br>
     *       This optional argument is used as the format template to<br>
     *       decode the value in the "value" parameter. Currently only used<br>
     *       for DateTime data.<br>
     * <p>
     * @param attr Type: int
     * @param value Type: DataValue
     * @param type Type: DataValue
     * @param templateText Type: TextData (Input) (default in Forte: NIL)
     */
    public void addConstraint(int attr, DataValue value, DataValue type, TextData templateText) {
        DataValue kind = null;

        if (attr > this.getNumAttrs()) {

            throw new Error(Error.BQ_ILLEGAL_ATTR, "AddConstraint", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (type == null || !(value instanceof TextData)) {

            // no need to parse or do SetValue() on "value".
            this.addConstraint(attr, ConstraintOperation.OP_EQ, value);

        }
        else if (type instanceof TextData) {

            TextData v = (TextData)value;
            v.setOffset(0);

            if (v.moveToChar("%_")) {
                this.addConstraint(attr, ConstraintOperation.OP_LIKE, value);
            }
            else if (v.getActualSize() == 4 && v.moveToString("NULL", false, true)) {
                this.addConstraint(attr, ConstraintOperation.OP_NULL, (DataValue)null);
            }
            else {
                this.addConstraint(attr, ConstraintOperation.OP_EQ, value);
            }

        }
        else if (!(type instanceof NumericData) && !(type instanceof DateTimeData)) {

            kind = CloneHelper.clone(type, false);
            kind.setValue(value);
            this.addConstraint(attr, ConstraintOperation.OP_EQ, kind);

        }
        else {

            //
            //  It is numeric or date; do our fancy parse thing
            //

            TextData v = (TextData)CloneHelper.clone(value, true);

            v.toLower();
            v.trimTrailing();
            v.trimLeading();
            v.setOffset(0);

            if (v.isDigit()) {
                //
                //  The first character is numeric -- use the whole value as the
                //  value in a simple equality constraint.
                //
                kind = CloneHelper.clone(type, false);
                this.setValueTemplate(kind, value, templateText);
                this.addConstraint(attr, ConstraintOperation.OP_EQ, kind);

            }
            else {

                Array_Of_TextData<TextData> words = new Array_Of_TextData<TextData>();
                int i = 0;
                int op = 0;
                boolean hasNot = false;

                //
                //  Parse the text into words.  Legal delimiters are <, >, =, !, ^, (,
                //  ), and blank.  Any delimiter except blank becomes a word itself,
                //  blanks disappear.
                //
                while (v.moveToChar("><=!^() ")) {
                    if (i != v.getOffset()) {
                        words.add(v.copyRange(i, v.getOffset()));
                    }
                    if (!(v.isChar(" "))) {
                        i = v.getOffset();
                        if (v.getActualSize() > v.getOffset()+1 && v.isChar("<>!^") && v.copyRange(v.getOffset()+1, v.getOffset()+2).isChar(">=")) {
                            words.add(v.copyRange(v.getOffset(), v.getOffset()+2));
                            v.moveNext();
                        }
                        else {
                            words.add(v.copyRange(v.getOffset(), v.getOffset()+1));
                        }
                        v.moveNext();
                    }
                    v.moveToNotChar(" ");
                    i = v.getOffset();
                }

                if (i < v.totalLength()) {
                    words.add(v.copyRange(i));
                }

                i = 1;

                if (i > words.size()) {
                    throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, v, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }

                if ("not".equals(words.get(i-1).toString())) {
                    i = i+1;
                    hasNot = true;
                    if (i > words.size()) {
                        throw new Error(Error.BQ_CONS_ONLYNOT, "AddConstraint", this, v, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                }

                if ("null".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_NULL;
                }
                else if ("between".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_BETWEEN;
                }
                else if ("in".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_IN;
                }
                else if (">".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_GT;
                }
                else if (">=".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_GE;
                }
                else if ("<".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_LT;
                }
                else if ("<=".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_LE;
                }
                else if ("=".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_EQ;
                }
                else if ("<>".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_NE;
                }
                else if ("!=".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_NE;
                }
                else if ("^=".equals(words.get(i-1).toString())) {
                    op = ConstraintOperation.OP_NE;
                }
                else if (templateText != null) {
                    words.add(i-1, new TextData("="));
                    op = ConstraintOperation.OP_EQ;
                }
                else {
                    throw new Error(Error.BQ_CONS_ILLEGAL_OP, "AddConstraint", this, v, words.get(i-1)).getException();
                }

                if (this.getConstraint() == null) {
                    this.setConstraint(new QueryConstraint());
                }

                if (op == ConstraintOperation.OP_NULL) {

                    if (i != words.size()) {
                        throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                    if (hasNot) {
                        this.addConstraint(attr, ConstraintOperation.OP_NOTNULL, (DataValue)null);
                        hasNot = false;
                    }
                    else {
                        this.addConstraint(attr, ConstraintOperation.OP_NULL, (DataValue)null);
                    }

                }
                else if (op == ConstraintOperation.OP_BETWEEN) {

                    if (type instanceof NumericData) {
                        if (i+3 != words.size()) {
                            throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                        }
                        else if (!("and".equals(words.get(i+2-1).toString()))) {
                            throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                        }
                        kind = CloneHelper.clone(type, false);
                        this.setValueTemplate(kind, words.get(i+3-1), templateText);
                        this.getConstraint().addValue(kind);
                        kind = CloneHelper.clone(type, false);
                        this.setValueTemplate(kind, words.get(i+1-1), templateText);
                        this.addConstraint(attr, op, kind);
                    }
                    else {
                        if (i+3 > words.size()) {
                            throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                        }
                        int andIx = 0;
                        for (int j = i+2; j <= words.size()-1; j++) {
                            if ("and".equals(words.get(j-1).toString())) {
                                andIx = j;
                                continue;
                            }
                        }
                        if (andIx == 0) {
                            throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                        }
                        for (int j = i+2; j <= andIx-1; j++) {
                            words.get(i+1-1).concat(" ");
                            words.get(i+1-1).concat(words.get(j-1));
                        }
                        for (int j = andIx+2; j <= words.size(); j++) {
                            words.get(andIx+1-1).concat(" ");
                            words.get(andIx+1-1).concat(words.get(j-1));
                        }
                        kind = CloneHelper.clone(type, false);
                        this.setValueTemplate(kind, words.get(andIx+1-1), templateText);
                        this.getConstraint().addValue(kind);

                        kind = CloneHelper.clone(type, false);
                        this.setValueTemplate(kind, words.get(i+1-1), templateText);
                        this.addConstraint(attr, op, kind);
                    }

                }
                else if (op == ConstraintOperation.OP_IN) {

                    if (type instanceof DateTimeData) {
                        throw new Error(Error.BQ_CONS_CANT_USE_DATE_WITH_IN, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                    if (words.size() < i+3) {
                        throw new Error(Error.BQ_CONS_ILLEGAL, "AddConstraint", this, value, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                    SqlData sqlData = new SqlData();
                    TextData sqlText = new TextData();
                    for (int j = i+2; j <= words.size()-1; j++) {
                        kind = CloneHelper.clone(type, false);
                        this.setValueTemplate(kind, words.get(j-1), templateText);
                        sqlData.getValues().add(kind);
                        sqlText.concat("?,");
                    }
                    sqlText.cutRange(sqlText.lengthToEnd()-1);
                    this.getConstraint().addSqlData(sqlData);
                    this.getConstraint().addValue(sqlText);
                    this.getConstraint().addAttr(this, attr, 1);
                    this.getConstraint().addOperation(op);

                }
                else {

                    i = i+1;
                    if (i != words.size()) {
                        for (int j = i+1; j <= words.size(); j++) {
                            words.get(i-1).concat(" ");
                            words.get(i-1).concat(words.get(j-1));
                        }
                    }
                    kind = CloneHelper.clone(type, false);
                    this.setValueTemplate(kind, words.get(i-1), templateText);
                    this.addConstraint(attr, op, kind);

                }

                if (hasNot) {
                    this.getConstraint().addOperation(ConstraintOperation.OP_NOT);
                }

            }

        }
    }
    public void addConstraint(int attr, DataValue value, DataValue type) {
      this.addConstraint(attr, value, type, null);
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method is used to limit the values of attributes for<br>
     *     BusinessClasses being selected.<br>
     * <p>
     *     AddConstraint pushes the value, attribute, and operation onto the<br>
     *     Constraint stack.  The constraints are anded together by default.<br>
     *     More complex relationships on the Constraint stack are supported but<br>
     *     no interface is provided on BusinessQuery to construct them.  The<br>
     *     Constraint stack can be manipulated directly if necessary.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying an attribute<br>
     *       whose value should be limited.<br>
     * <p>
     *     operation<br>
     *       The operation parameter specifies the relationship the attribute<br>
     *       should bear to the value.  Values for operation are defined in<br>
     *       the ConstraintOperation class.<br>
     * <p>
     *     value<br>
     *       The value parameter specifies the value to which the attribute<br>
     *       should be limited.<br>
     * <p>
     * @param attr Type: int
     * @param operation Type: int
     * @param value Type: DataValue (Input) (default in Forte: NIL)
     */
    public void addConstraint(int attr, int operation, DataValue value) {
        if (attr > this.getNumAttrs()) {

            throw new Error(Error.BQ_ILLEGAL_ATTR, "AddConstraint", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (this.operation == BusinessQuery.OP_INSERT) {

            throw new Error(Error.BQ_ILLEGAL_ACTION_FOR_OP, "AddConstraint", this, new IntegerData(this.operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (this.getConstraint() == null) {
            this.setConstraint(new QueryConstraint());
        }

        if ((operation&ConstraintOperation.TYPE_MASK) == ConstraintOperation.TYPE_ORDERBY) {

            //
            //  Check that this attr isn't already specified in an "order by" constraint
            //
            for (int i = this.getConstraint().getStack().size(); i >= 2; i--) {
                if (this.getConstraint().getStack().get(i-1) instanceof ConstraintOperation && ((((ConstraintOperation)(this.getConstraint().getStack().get(i-1))).getOperation()&ConstraintOperation.TYPE_MASK) == ConstraintOperation.TYPE_ORDERBY) && ((ConstraintAttr)(this.getConstraint().getStack().get(i-1-1))).getAttr() == attr && ((ConstraintAttr)(this.getConstraint().getStack().get(i-1-1))).getEntity() == this) {
                    throw new Error(Error.BQ_CONS_DUP_ORDERBY_ATTR, "AddConstraint", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }
            }

            if (value != null) {
                this.getConstraint().addValue(value);
            }


        }
        else if (operation == ConstraintOperation.OP_NULL || operation == ConstraintOperation.OP_NOTNULL) {
            if (value != null) {
                throw new Error(Error.BQ_CONS_OP_PROHIBITS_VALUE, "AddConstraint", this, new IntegerData(operation), new IntegerData(attr)).getException();
            }

        }
        else if (value == null) {
            throw new Error(Error.BQ_CONS_OP_NEEDS_VALUE, "AddConstraint", this, new IntegerData(operation), new IntegerData(attr)).getException();

        }
        else {
            this.getConstraint().addValue(value);

        }

        this.getConstraint().addAttr(this, attr, 1);
        this.getConstraint().addOperation(operation);
    }
   
    public void addConstraint(int attr, int operation){
      this.addConstraint(attr, operation, null);
    }

    /**
     * addForeignConstraint<p>
     * AddForeignConstraint<br>
     *     The AddForeignConstraint method adds a constraint on a foreign class<br>
     *     which limits this class.  This is as opposed to the constraints on the<br>
     *     foreign class's query as added by AddAttr which are used to limit the<br>
     *     foreign class itself.<br>
     * <p>
     *     When would you want to use a foreign constraint on the independent<br>
     *     class (this case) vs. a constraint on the foreign class?  Glad<br>
     *     you asked.  Assume the model application with orders and line items.<br>
     *     If you wanted to get all the orders which have one or more line<br>
     *     items which are widgets.  You would need this method because you<br>
     *     want to constrain the independent class (orders in this case) by the<br>
     *     foreign class (line items).  If you wanted to get only the line<br>
     *     items which were widgets then you would constrain the line item<br>
     *     query which you used to specify the line items (the one you used in<br>
     *     the AddAttr call).<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying a dependent<br>
     *       attribute which should be used in limiting the independent class.<br>
     * <p>
     *     query<br>
     *       The query parameter specifies a BusinessQuery describing<br>
     *       constraints of the dependent class for which the independent<br>
     *       class should be limited.<br>
     * <p>
     * @param attr Type: int
     * @param query Type: BusinessQuery
     */
    public void addForeignConstraint(int attr, BusinessQuery query) {
        query.clearAttrs(true);

        this.addAttr(attr, query);
    }

    /**
     * addJoinConstraint<p>
     * AddJoinConstraint<br>
     *     The AddJoinConstraint method is used to join one entity to another.<br>
     * <p>
     *     NOTE:  You don't normally need to invoke this directly.  It is done<br>
     *     implicitly whenever you specify a constraint on a foreign entity or<br>
     *     use AddForeignConstraint.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying which attribute<br>
     *       should be joined.<br>
     * <p>
     *     operation<br>
     *       The operation parameter specifies the relationship the attribute<br>
     *       should bear to the value.  Values for operation are defined in<br>
     *       the ConstraintOperation class.  Legal values are:<br>
     *       ConstraintOperation.EQUIJOIN, ConstraintOperation.LEFTJOIN, and<br>
     *       ConstraintOperation.RIGHTJOIN.<br>
     * <p>
     *     foreignClass<br>
     *       The foreignClass parameter specifies the entity which is to be<br>
     *       joined against.<br>
     * <p>
     *     foreignAttr<br>
     *       The foreignAttr parameter specifies the attribute in the<br>
     *       foreign entity which is to be joined to attr.<br>
     * <p>
     * @param operation Type: int
     * @param foreignClass Type: BusinessQuery
     */
    public void addJoinConstraint(int operation, BusinessQuery foreignClass) {
        if (this.getConstraint() == null) {
            this.setConstraint(new QueryConstraint());
        }

        Array_Of_QueryAttrMap<QueryAttrMap> attrMap = this.getForeignAttrMap(foreignClass.getParentAttr());

        if (attrMap != null) {
            for (QueryAttrMap attr : attrMap) {
                this.getConstraint().addAttr(foreignClass, attr.getForeign(), 1);
                this.getConstraint().addAttr(this, attr.getLocal(), 1);
            }
        }

        this.getConstraint().addOperation((operation&ConstraintOperation.OPCODE_MASK)+(attrMap.size()*ConstraintOperation.PCOUNT_INCREMENT));
    }

    /**
     * buildQuery<p>
     * BuildQuery<br>
     *     The BuildQuery method builds an SQL query for ourself.<br>
     * <p>
     *     NOTE:  You don't normally need to invoke this directly.  It is used<br>
     *     by the BusinessMgr to build the query they must execute.<br>
     * <p>
     *     sqlQuery<br>
     *       The sqlQuery parameter is used to return the SQLquery built.  If the<br>
     *       sqlQuery parameter is non NIL on input then it represents a partially<br>
     *       built sqlQuery to which we should append our sqlQuery.<br>
     * <p>
     * @param query Type: SqlQuery
     */
    public void buildQuery(ParameterHolder_SqlQuery query) {
        if ((this.getExecuteInfo().getStatus()&QueryExecuteInfo.ST_BUILT) > 0) {
            return;
        }

        int t = 0, t2 = 0;
        // holds a table index
        TextData c = null;
        // holds a column name
        SqlQuery sq = null;
        // holds the current SqlQuery;
        int lNumKeyAttrs = this.getNumKeyAttrs();
        // local copy of virtual attribute
        int lNumTables = this.getNumTables();
        // local copy of virtual attribute

        if (((SqlQuery)query.getObject()) == null) {
            query.setObject(this.getSqlQuery((DBConnectionManager)null));
        }

        sq = (SqlQuery)query.getObject();

        //
        //  Add tables for this BusinessClass to the from clause of the query.
        //
        this.describeTables(sq);

        switch (this.operation) {

            case BusinessQuery.OP_UPDATE: {

                //
                //  Specify updated values.
                // 
                sq.addValue(this.getValues());

                //
                //  Add constraints to specify which entity is to be updated.
                //
                for (int i = 1; i <= lNumKeyAttrs; i++) {
                    for (int t1 = 1; t1 <= lNumTables; t1++) {
                        t2 = t1;
                        // ------------------------------------
                        // Parameters for call to GetColumnName
                        // ------------------------------------
                        ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t2);
                        ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                        this.getColumnName(i, qq_tableIndex, qq_columnName);
                        t2 = qq_tableIndex.getInt();
                        c = (TextData)qq_columnName.getObject();
                        sq.addConstraint(t2, c, ConstraintOperation.OP_EQ, this.getKey().getValues().get(i-1));
                    }
                }

                //
                //  Add user specified constraints.
                //
                sq.addConstraint(this.getConstraint());

                break;
            }
            case BusinessQuery.OP_INSERT: {

                //
                //  For inserts the constraints represent the values to be inserted.
                //
                sq.addValue(this.getValues());

                break;
            }
            case BusinessQuery.OP_DELETE: {

                //
                //  For deletes we need only specify the key attributes as constraints.
                //
                for (int i = 1; i <= lNumKeyAttrs; i++) {
                    for (int t1 = 1; t1 <= lNumTables; t1++) {
                        t2 = t1;
                        // ------------------------------------
                        // Parameters for call to GetColumnName
                        // ------------------------------------
                        ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t2);
                        ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                        this.getColumnName(i, qq_tableIndex, qq_columnName);
                        t2 = qq_tableIndex.getInt();
                        c = (TextData)qq_columnName.getObject();
                        sq.addConstraint(t2, c, ConstraintOperation.OP_EQ, this.getKey().getValues().get(i-1));
                    }
                }

                //
                //  Add user specified constraints.
                //
                sq.addConstraint(this.getConstraint());

                break;
            }
            case BusinessQuery.OP_SELECT: {

                //
                // Add attributes to the select list.
                //   
                int attrs = 0;
                int index = 0;
                int baseIndex = 1;
                int lNumDBAttrs = this.getNumDBAttrs();
                // cache virtual attribute

                if (this.getTargetAttrs() != null) {
                    for (IntegerData attr : this.getTargetAttrs()) {
                        if (baseIndex+30 <= lNumKeyAttrs) {
                            //
                            //  All attributes are key attributes -- make sure they're all set.
                            //
                            attr.setValue(2147483647);
                        }
                        else if (baseIndex <= lNumKeyAttrs) {
                            //
                            //  Or in key attributes
                            //
                            attr.setValue(attr.getValue()|((int)(new DoubleData().power(2, lNumKeyAttrs-baseIndex+1).getValue()-1)));
                        }
                        index = baseIndex;
                        attrs = attr.getValue();
                        while ((attrs > 0) && (index <= lNumDBAttrs)) {
                            if ((attrs&1) > 0) {
                                t = 1;
                                // ------------------------------------
                                // Parameters for call to GetColumnName
                                // ------------------------------------
                                ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
                                ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                                this.getColumnName(index, qq_tableIndex, qq_columnName);
                                t = qq_tableIndex.getInt();
                                c = (TextData)qq_columnName.getObject();
                                sq.addColumn(t, c, (DataValue)null);
                                if (index <= lNumKeyAttrs && lNumTables > 1) {
                                    for (int tindex = 2; tindex <= lNumTables; tindex++) {
                                        t2 = tindex;
                                        // ------------------------------------
                                        // Parameters for call to GetColumnName
                                        // ------------------------------------
                                        ParameterHolder_integer qq_tableIndex1 = new ParameterHolder_integer(t2);
                                        ParameterHolder_TextData qq_columnName1 = new ParameterHolder_TextData();
                                        this.getColumnName(index, qq_tableIndex1, qq_columnName1);
                                        t2 = qq_tableIndex1.getInt();
                                        c = (TextData)qq_columnName1.getObject();
                                        if (this.getConstraint() == null) {
                                            this.setConstraint(new QueryConstraint());
                                        }
                                        this.getConstraint().addAttr(this, index, 1);
                                        this.getConstraint().addAttr(this, index, tindex);
                                        this.getConstraint().addOperation(ConstraintOperation.OP_EQ);
                                    }
                                }
                            }
                            attrs = attrs/2;
                            index = index+1;
                        }
                        baseIndex = baseIndex+31;
                    }
                }

                //
                // Finally do foreign entities.
                //
                if (this.getForeignClasses() != null) {
                    for (BusinessQuery fe : this.getForeignClasses()) {

                        if ((fe.getExecuteInfo().getStatus()&QueryExecuteInfo.ST_JOINED) > 0) {
                            //
                            //  Check what kind of join we are going to do
                            //
                            int op = 0;
                            if ((fe.getParentMult()&BusinessQuery.ASSOC_MULT_OPTIONAL) == 0) {
                                op = ConstraintOperation.OP_EQUIJOIN;
                                sq.setOptions(sq.getOptions()|SqlQuery.OPT_INNER_JOIN);
                            }
                            else {
                                op = ConstraintOperation.OP_LEFTJOIN;
                                sq.setOptions(sq.getOptions()|SqlQuery.OPT_OUTER_JOIN);
                            }

                            //
                            //  Put in a join to the foreign table
                            //
                            this.addJoinConstraint(op, fe);

                            //
                            //  Now have the foreign entity describe itself as we just did and
                            //  append this to the sqlQuery we are building up.
                            //
                            // ---------------------------------
                            // Parameters for call to BuildQuery
                            // ---------------------------------
                            ParameterHolder_SqlQuery qq_query = new ParameterHolder_SqlQuery(sq);
                            fe.buildQuery(qq_query);
                            sq = (SqlQuery)qq_query.getObject();

                        }
                        else if (fe.getTargetAttrs() == null) {
                            //
                            //  This is the case where we have a 1-to-many association
                            //  which has a constraint on the foreign class which is
                            //  suppossed to limit the primary.  We need an "in" sql
                            //  condition of the form:
                            //    where (<join-column-list>) in
                            //      (select <join-column-list> from <foreignTable> ...)
                            //       
                            TextData queryText = null;
                            SqlQuery subQuery = null;

                            // ---------------------------------
                            // Parameters for call to BuildQuery
                            // ---------------------------------
                            ParameterHolder_SqlQuery qq_query = new ParameterHolder_SqlQuery(subQuery);
                            fe.buildQuery(qq_query);
                            subQuery = (SqlQuery)qq_query.getObject();
                            //
                            //  Don't really want this query to look like its executed.
                            //
                            fe.getExecuteInfo().setStatus(fe.getExecuteInfo().getStatus()&~QueryExecuteInfo.ST_BUILT);

                            //
                            //  First build the sub-query and get its text.  Note:
                            //  this query really has the wrong column list.  We'll
                            //  fix that up and reset the query text in a minute, but
                            //  need to get the text now as input data isn't
                            //  computed until we do and we need to know that now.
                            //
                            queryText = subQuery.getText().get(0);

                            if (subQuery.getData().get(0).getValues().size() > 0) {
                                //
                                //  Push input data for the sub-query, if any.
                                //
                                this.getConstraint().addSqlData(subQuery.getData().get(0));
                            }

                            //  Next push the suq-query, we'll fix this up at the end.
                            //
                            this.getConstraint().addValue(queryText);

                            subQuery.clearColumnList();
                            //
                            //  Now clear the column list and recompute it.  At the
                            //  same time push on the column list for the outer query.
                            //       
                            Array_Of_QueryAttrMap<QueryAttrMap> qq_localVector = this.getForeignAttrMap(fe.getParentAttr());
                            if (qq_localVector != null) {
                                for (QueryAttrMap attr : qq_localVector) {
                                    t = 1;
                                    // ------------------------------------
                                    // Parameters for call to GetColumnName
                                    // ------------------------------------
                                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
                                    ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                                    fe.getColumnName(attr.getForeign(), qq_tableIndex, qq_columnName);
                                    t = qq_tableIndex.getInt();
                                    c = (TextData)qq_columnName.getObject();
                                    subQuery.addColumn(t, c, (DataValue)null);
                                    this.getConstraint().addAttr(this, attr.getLocal(), 1);
                                }
                            }

                            //  Now we get the real sub-query we want with the correct
                            //  column list.
                            //
                            queryText.setValue( subQuery.getText().get(0) );

                            //  Finally push the IN operator.
                            //
                            this.getConstraint().addOperation(ConstraintOperation.OP_IN);

                        }
                    }
                }

                sq.addConstraint(this.getConstraint());

                break;
            }

            default: {
                throw new Error(Error.BQ_ILLEGAL_OPERATION, "BuildQuery", this).getException();

            }
        }

        this.getExecuteInfo().setStatus(this.getExecuteInfo().getStatus()|QueryExecuteInfo.ST_BUILT);
    }

    /**
     * clearAttrs<p>
     * ClearAttrs<br>
     *     The ClearAttrs method is used to clear the TargetAttrs for a<br>
     *     BusinessQuery.<br>
     * <p>
     *     deep<br>
     *       The deep parameter specifies whether TargetAttrs of Foreign<br>
     *       BusinessQueries should be cleared as well.<br>
     * <p>
     * @param deep Type: boolean (Input) (default in Forte: FALSE)
     */
    public void clearAttrs(boolean deep) {
        this.setTargetAttrs(null);

        if (deep && this.getForeignClasses() != null) {
            if (this.getForeignClasses() != null) {
                for (BusinessQuery f : this.getForeignClasses()) {
                    f.clearAttrs(deep);
                }
            }
        }
    }

    /**
     * clearConstraints<p>
     * ClearConstraints<br>
     *     The ClearConstraints method is used to clear the constraints for a<br>
     *     BusinessQuery which is used for a select.<br>
     * <p>
     *     deep<br>
     *       The deep parameter specifies whether Constraints of Foreign<br>
     *       BusinessQueries should be cleared as well.<br>
     * <p>
     * @param deep Type: boolean (Input) (default in Forte: FALSE)
     */
    public void clearConstraints(boolean deep) {
        if (this.operation != BusinessQuery.OP_SELECT) {
            throw new Error(Error.BQ_CANT_RESET, "ClearConstraints", this).getException();
        }
        else {
            this.setConstraint(null);
        }

        if (deep && this.getForeignClasses() != null) {
            if (this.getForeignClasses() != null) {
                for (BusinessQuery f : this.getForeignClasses()) {
                    f.clearConstraints(deep);
                }
            }
        }
    }
    /**
     * Same as {@link #clearConstraints(boolean) with the boolean value defaulter to false
     */
    public void clearConstraints(){
      this.clearConstraints(false);
    }

    /**
     * clearForeignAttrs<p>
     * ClearForeignAttrs<br>
     *     The ClearForeignAttrs method is used to remove foreign queries from a<br>
     *     BusinessQuery.<br>
     * <p>
     */
    public void clearForeignAttrs() {
        this.setForeignClasses(null);
    }

    /**
     * connectQueries<p>
     * ConnectQueries<br>
     *     The ConnectQueries method adds querries on foreign classes of source to<br>
     *     us as foreign queries.  It also recursively adds foreign queries of<br>
     *     the foreign classes to the foreign class's queries.  ConnectQueries is<br>
     *     used by the class' client's Update method to connect all the<br>
     *     queries for processing by the class' manager's Update method.<br>
     * <p>
     *     source<br>
     *       The source parameter specifies the BusinessClass whose foreign<br>
     *       attributes are to be checked for queries.  It's Query attribute<br>
     *       should be us!<br>
     * <p>
     * @param source Type: BusinessClass
     * @param client Type: BusinessClient
     */
    @SuppressWarnings("unchecked")
  public void connectQueries(BusinessClass source, BusinessClient client) {
        if (source.getUpdateQuery() != this) {
            throw new Error(Error.BQ_WRONG_ENTITY, "ConnectQueries", this).getException();
        }

        Array_Of_BusinessClass<BusinessClass> foreignClasses = null;
        BusinessClass foreignClass = null;
        int mult = 0;

        for (int i = 1; i <= this.getNumForeignAttrs(); i++) {

            mult = this.getForeignAttrMult(BusinessQuery.ATTR_FOREIGN+i);

            if ((mult&BusinessQuery.ASSOC_MULT_ONE_MASK) > 0) {

                // ------------------------------
                // Parameters for call to GetAttr
                // ------------------------------
                ParameterHolder_BusinessClass qq_value = new ParameterHolder_BusinessClass();
                source.getAttr(BusinessQuery.ATTR_FOREIGN+i, qq_value);
                foreignClass = (BusinessClass)qq_value.getObject();

                if (foreignClass != null && foreignClass.getUpdateQuery() != null && ((foreignClass.getInstanceStatus()&(BusinessClass.ST_UPDATE|BusinessClass.ST_DELETE|BusinessClass.ST_INSERT)) > 0)) {
                    //
                    //  Found a foreign class with changes -- validate it and hook the
                    //  foreign class's query up to us.
                    //
                    foreignClass.validateInstance(client);
                    this.addAttr(BusinessQuery.ATTR_FOREIGN+i, foreignClass.getUpdateQuery());

                    //
                    //  Recursively hook up any dependent querries on this
                    //  dependent query to it.
                    //
                    foreignClass.getUpdateQuery().connectQueries(foreignClass, client);

                }

            }
            else {

                // ------------------------------
                // Parameters for call to GetAttr
                // ------------------------------
                ParameterHolder_BusinessClass_Array qq_value = new ParameterHolder_BusinessClass_Array();
                source.getAttr(BusinessQuery.ATTR_FOREIGN+i, qq_value);
                foreignClasses = (Array_Of_BusinessClass<BusinessClass>)qq_value.getObject();

                if (foreignClasses != null) {

                    if (foreignClasses != null) {
                        for (BusinessClass fe : foreignClasses) {

                            if (fe.getUpdateQuery() != null && ((fe.getInstanceStatus()&(BusinessClass.ST_UPDATE|BusinessClass.ST_DELETE|BusinessClass.ST_INSERT)) > 0)) {

                                //
                                //  Found a foreign class with changes -- validate it and hook the
                                //  foreign  class's query up to us.
                                //
                                fe.validateInstance(client);
                                this.addAttr(BusinessQuery.ATTR_FOREIGN+i, fe.getUpdateQuery());

                                //
                                //  Recursively hook up any foreign queries on this
                                //  foreign query to it.
                                //
                                fe.getUpdateQuery().connectQueries(fe, client);

                            }

                        }
                    }

                }

            }

        }
    }

    /**
     * describeTables<p>
     * DescribeTables<br>
     *     The DescribeTables method is used to add the table names for this<br>
     *     BusinessClass to the query.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BuildQuery method uses it internally.<br>
     * <p>
     *     DescribeTables will use SqlQuery.AddTable to add the actual<br>
     *     table name to the query.  AddTable will return a unique table alias<br>
     *     that we need to use when referencing columns in the table either in<br>
     *     the select list or the where clause, which we will remember in the<br>
     *     TableAliases array.<br>
     * <p>
     *     sqlQuery<br>
     *       The sqlQuery parameter contains the SqlQuery which is being used<br>
     *       to construct the SQL for this BusinessQuery.<br>
     * <p>
     * @param sqlQuery Type: SqlQuery
     */
    public void describeTables(SqlQuery sqlQuery) {
        TextData tableName = null;

        if (this.getTableAliases() == null) {
            this.setTableAliases(new Array_Of_IntegerData<IntegerData>());
        }

        for (int i = 1; i <= this.getNumTables(); i++) {
            // -----------------------------------
            // Parameters for call to GetTableName
            // -----------------------------------
            ParameterHolder_TextData qq_tableName = new ParameterHolder_TextData();
            this.getTableName(i, qq_tableName);
            tableName = (TextData)qq_tableName.getObject();
            this.getTableAliases().add(sqlQuery.addTable(tableName));
        }
    }

    /**
     * disconnectQueries<p>
     * DisconnectQueries<br>
     *     The DisconnectQueries method removes.<br>
     * <p>
     */
    public void disconnectQueries() {
        if (this.getForeignClasses() != null) {
            for (BusinessQuery q : this.getForeignClasses()) {
                q.disconnectQueries();
            }
        }

        this.setForeignClasses(null);
    }

    /**
     * getAttrName<p>
     * GetAttrName<br>
     *     The GetAttrName method is used to get the name of the attribute<br>
     *     indicated by the attr parameter.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying for which<br>
     *       attribute the name should be returned.<br>
     * <p>
     * @param attr Type: int
     * @return String
     */
    public String getAttrName(int attr) {
        throw new Error(Error.BQ_ILLEGAL_ATTR, "GetAttrName", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * getColumnName<p>
     * GetColumnName<br>
     *     The GetColumnName method is used to get the column and table name in<br>
     *     the underlying database which holds the attribute indicated by the<br>
     *     attr parameter.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     SQLquery class uses it to create the text of the query.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying for which<br>
     *       attribute table and column info should be returned.<br>
     * <p>
     *     tableIndex<br>
     *       The tableIndex parameter returns an index which indicates which<br>
     *       of the tables that comprise this BusinessClass holds attr.<br>
     * <p>
     *     columnName<br>
     *       The columnName parameter returns the name of the column in the<br>
     *       table indicated by the tableIndex parameter which holds attr.<br>
     * <p>
     * @param attr Type: int
     * @param tableIndex Type: int
     * @param columnName Type: TextData
     */
    public void getColumnName(int attr, ParameterHolder_integer tableIndex, ParameterHolder_TextData columnName) {
        throw new Error(Error.BQ_ILLEGAL_ATTR, "GetColumnName", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * qq_getExecuteInfo<p>
     * Method renamed by jcTOOL from GetExecuteInfo to qq_getExecuteInfo
     * because it conflicted with an attribute<p>
     * <p>
     * @return QueryExecuteInfo
     */
    public QueryExecuteInfo qq_getExecuteInfo() {
        if (this._ExecuteInfo == null) {
            this._ExecuteInfo = new QueryExecuteInfo();
        }

        return this._ExecuteInfo;
    }

    /**
     * getForeignAttrMap<p>
     * GetForeignAttrMap<br>
     *     The GetForeignAttrMap method is used to get the mapping between<br>
     *     simple attributes of this entity to the corresponding simple attributes<br>
     *     of the foreign entity indicated by the attr parameter.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BuildQuery method uses it internally.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying for which<br>
     *       foreign attribute a mapping of local to foreign attributes is<br>
     *       needed.<br>
     * <p>
     *     Returns<br>
     *       The return value is an array of mappings between simple attributes<br>
     *       of this entity to simple attributes of the foreign entity.<br>
     * <p>
     * @param attr Type: int
     * @return Array_Of_QueryAttrMap<QueryAttrMap>
     */
    public Array_Of_QueryAttrMap<QueryAttrMap> getForeignAttrMap(int attr) {
        throw new Error(Error.BQ_ILLEGAL_ATTR, "GetForeignAttrMap", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * getForeignAttrMgr<p>
     * GetForeignAttrMgr<br>
     *     The GetForeignAttrMgr method is used to get the index of the BusinessMgr<br>
     *     associated with the attribute specified by the attr parameter.  The<br>
     *     Index is used by the BusinessQuery's BusinessMgr to index his<br>
     *     DependentMgr array to find the actual BusinessMgr to use for<br>
     *     the attribute specifed by the attr parameter.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BusinessMgr class uses it internally.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying for which<br>
     *       attribute a BusinessMgr index should be returned.<br>
     * <p>
     * @param attr Type: int
     * @return int
     */
    public int getForeignAttrMgr(int attr) {
        throw new Error(Error.BQ_ILLEGAL_ATTR, "GetForeignAttrMgr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * getForeignAttrMult<p>
     * GetForeignAttrMult<br>
     *     The GetForeignAttrMult method is used to get information about the<br>
     *     multiplicity of the association between this class and the foreign<br>
     *     class specified by the attr parameter.  Legal values are any<br>
     *     combination of:<br>
     *       ASSOC_MULT_OPTIONAL   (there may be one foreign object)<br>
     *       ASSOC_MULT_TO_ONE    (there is one foreign object)<br>
     *       ASSOC_MULT_TO_MANY    (there may be many foreign objects)<br>
     *       ASSOC_AGGREGATION<br>
     *       ASSOC_MULT_ONE_TO<br>
     *       ASSOC_MULT_MANY_TO<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BusinessQuery class uses it internally.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying for which<br>
     *       foreign attribute information should be returned.<br>
     * <p>
     * @param attr Type: int
     * @return int
     */
    public int getForeignAttrMult(int attr) {
        throw new Error(Error.BQ_ILLEGAL_ATTR, "GetForeignAttrMult", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * getMgrID<p>
     * GetMgr<br>
     *     The GetMgr method is used to get the ID of the BusinessMgr<br>
     *     associated with the query.  The ID is used by the BusinessServiceMgr<br>
     *     to index his Mgrs array to find the actual BusinessMgr to use for<br>
     *     the query.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BusinessServiceMgr class uses it internally.<br>
     * <p>
     * @return int
     */
    public int getMgrID() {
        throw new Error(Error.GEN_UNIMPLEMENTED, "GetMgrID", this).getException();
    }

    /**
     * getNumAttrs<p>
     * GetNumAttrs<br>
     *     The GetNumAttrs method is used to get the number of attributes of a<br>
     *     given kind.  The kinds which can be requests are simple attributes.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BusinessQuery class uses it internally.<br>
     * <p>
     *     kind<br>
     *       The kind parameter specifies what kind of attributes are of<br>
     *       interest.  Legal values are:<br>
     * <p>
     *       Value      Meaning<br>
     *       -----      -------<br>
     *       ATTR_KEY    Return the number of attributes which comprise the<br>
     *               key.  Note: the key attributes must be the FIRST<br>
     *               ATTR_KEY attributes (i.e. 1 to ATTR_KEY).<br>
     *       ATTR_DB      Return the number of database attributes.<br>
     *       ATTR_SIMPLE    Return the number of simple attributes.<br>
     *       ATTR_FOREIGN  Return the number of foreign attributes.<br>
     *       Anything else  Return 0.<br>
     * <p>
     *     Returns<br>
     *       The return value specifies the number of attributes this entity<br>
     *       has of the kind specified by the kind parameter.<br>
     * <p>
     * @param kind Type: int (Input) (default in Forte: 0)
     * @return int
     */
    public int getNumAttrs(int kind) {
        return 0;
    }
   
    /**
     * qq_getNumTables<p>
     * Method renamed by jcTOOL from GetNumTables to qq_getNumTables
     * because it conflicted with an attribute<p>
     * <p>
     * @return int
     */
    public int qq_getNumTables() {
        return 1;
    }

    // Method GetOperation() : integer skipped because it is replaced by accessor / mutator.
    /**
     * getOrderConstraints<p>
     * GetOrderConstraints<br>
     *     The GetOrderConstraints method gets all the "order by" constraints<br>
     *     from the BusinessQuery and the closure of all foreign BusinessQueries<br>
     *     of multiplicity  one.  The constraints are ordered such that any<br>
     *     "order by" constraint with position N is placed before any "order by"<br>
     *     constraint with position N+m, where m > 0.  Also any "order by"<br>
     *     constraint with no position (i.e. position < 0) are placed immediately<br>
     *     following the previous "order by" constraint with a position.  The<br>
     *     order of the "order by" constraints on the constraint stack is<br>
     *     changed to effect this ordering.<br>
     * <p>
     *     Returns<br>
     *       An ordered array of ConstraintAttr nodes.  The attr attribute is<br>
     *       negated for any "order by ... desc" constraints.<br>
     * <p>
     * @return Array_Of_ConstraintAttr<ConstraintAttr>
     */
    @SuppressWarnings("unchecked")
  public Array_Of_ConstraintAttr<ConstraintAttr> getOrderConstraints() {
        if (this.getExecuteInfo().getOrderBy() == null) {

            Array_Of_Object<Object> orderBy = new Array_Of_Object<Object>();
            // Array of Array of ConstraintAttr;
            Array_Of_BusinessQuery<BusinessQuery> queries = new Array_Of_BusinessQuery<BusinessQuery>();
            BusinessQuery q = null;
            int i = 0, j = 0, pos = 0;
            int insertAt = 1;
            Array_Of_ConstraintAttr<ConstraintAttr> temp = null;

            queries.add(this);

            j = 1;

            while (j <= queries.size()) {
                q = queries.get(j-1);

                //
                //  Add in any joined queries.
                //
                Array_Of_BusinessQuery<BusinessQuery> qq_localVector = q.getForeignClasses();
                if (qq_localVector != null) {
                    for (BusinessQuery fq : qq_localVector) {
                        if ((fq.getExecuteInfo().getStatus()&QueryExecuteInfo.ST_JOINED) > 0) {
                            queries.add(fq);
                        }
                    }
                }

                //
                //  Now pull out all "order by" constraints and insert them into our
                //  ordered "order by" list.
                //
                if (q.getConstraint() != null) {
                    i = 2;
                    while (i <= q.getConstraint().getStack().size()) {
                        if (q.getConstraint().getStack().get(i-1) instanceof ConstraintOperation && ((((ConstraintOperation)(q.getConstraint().getStack().get(i-1))).getOperation()&ConstraintOperation.TYPE_MASK) == ConstraintOperation.TYPE_ORDERBY)) {
                            pos =  -1;
                            if (i > 2 && q.getConstraint().getStack().get(i-2-1) instanceof ConstraintValue) {
                                pos = ((IntegerData)((ConstraintValue)(q.getConstraint().getStack().get(i-2-1))).getValue()).getValue();
                                q.getConstraint().getStack().deleteRow(i-2- 1);
                                i = i-1;
                            }
                            if (pos > 0) {
                                insertAt = pos+1;
                            }
                            if (orderBy.get(insertAt-1) == null) {
                                orderBy.set(insertAt-1, new Array_Of_ConstraintAttr<ConstraintAttr>());
                            }
                            if (((ConstraintOperation)(q.getConstraint().getStack().get(i-1))).getOperation() == ConstraintOperation.OP_ORDERBY_DESC) {
                                ((ConstraintAttr)(q.getConstraint().getStack().get(i-1-1))).setAttr( -((ConstraintAttr)(q.getConstraint().getStack().get(i-1-1))).getAttr());
                            }
                            temp = (Array_Of_ConstraintAttr)(orderBy.get(insertAt-1));
                            temp.add((ConstraintAttr)q.getConstraint().getStack().get(i-1-1));
                            q.getConstraint().getStack().deleteRow(i- 1);
                            q.getConstraint().getStack().deleteRow(i-1- 1);
                            i = i-2+1;
                        }
                        i = i+1;
                    }
                }

                j = j+1;

            }

            //
            //  Now we flatten the 2-level orderby array into a simple 1-level array
            //  and put the constraints back on the constraint stack.
            //
            this.getExecuteInfo().setOrderBy(new Array_Of_ConstraintAttr<ConstraintAttr>());
            if (orderBy != null) {
                for (Object oa : orderBy) {
                    if (this.getConstraint() == null) {
                        this.setConstraint(new QueryConstraint());
                    }
                    temp = (Array_Of_ConstraintAttr)oa;
                    if (temp != null) {
                        for (ConstraintAttr ob : temp) {
                            this.getExecuteInfo().getOrderBy().add(ob);
                            if (ob.getAttr() < 0) {
                                this.getConstraint().addAttr(ob.getEntity(),  -ob.getAttr(), 1);
                                this.getConstraint().addOperation(ConstraintOperation.OP_ORDERBY_DESC);
                            }
                            else {
                                this.getConstraint().addAttr(ob.getEntity(), ob.getAttr(), 1);
                                this.getConstraint().addOperation(ConstraintOperation.OP_ORDERBY);
                            }
                        }
                    }
                }
            }

        }

        return this.getExecuteInfo().getOrderBy();
    }

    /**
     * getQuery<p>
     * GetQuery<br>
     *     The GetQuery method is used to get the BusinessQuery associated with<br>
     *     the foreign or dependent attribute specified by the attr parameter.<br>
     *     This will be the BusinessQuery first passed in the AddAttr method<br>
     *     for this attribute.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, it is<br>
     *     used internally.<br>
     * <p>
     *     attr<br>
     *       The attr parameter specifies for which attribute the associated<br>
     *       BusinessQuery should be returned.  It should be for either a<br>
     *       foreign or dependent entity.<br>
     * <p>
     *     Returns<br>
     *       The return value specifies the BusinessQuery which is associated<br>
     *       with the attribute specified by the attr parameter.<br>
     * <p>
     * @param attr Type: int
     * @return BusinessQuery
     */
    public BusinessQuery getQuery(int attr) {
        if (attr <= BusinessQuery.ATTR_FOREIGN) {

            throw new Error(Error.BQ_ATTR_NOT_FOREIGN, "GetQuery", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else {

            if (this.getForeignClasses() != null) {
                for (BusinessQuery q : this.getForeignClasses()) {
                    if (q.getParentAttr() == attr) {
                        return q;
                    }
                }
            }

        }

        return null;
    }

    /**
     * getSqlQuery<p>
     * <p>
     * @param dBSession Type: DBConnectionManager (Input) (default in Forte: NIL)
     * @return SqlQuery
     */
    public SqlQuery getSqlQuery(DBConnectionManager dBSession) {
        return new SqlQuery().setup(this, this.operation, dBSession);
    }
   
    /**
     * getSqlQuery<p>
     * <p>
     * @return SqlQuery
     */
    public SqlQuery getSqlQuery() {
      return this.getSqlQuery(null);
    }   

    /**
     * getTableName<p>
     * GetTableName<br>
     *     The GetTableName method is used to get the table names in<br>
     *     the underlying database which holds the business class.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     SQLquery class uses it to create the text of the query.<br>
     * <p>
     *     tableIndex<br>
     *       The tableIndex parameter indicates for which of the tables that<br>
     *       comprise this BusinessClass the should be returned.<br>
     * <p>
     *     tableName<br>
     *       The tableName parameter returns the name of the table in the<br>
     *       database indicated by the tableIndex parameter.<br>
     * <p>
     * @param tableIndex Type: int
     * @param tableName Type: TextData
     */
    public void getTableName(int tableIndex, ParameterHolder_TextData tableName) {
        throw new Error(Error.BQ_ILLEGAL_TABLE_INDEX, "GetTableName", this, new IntegerData(tableIndex), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }

    /**
     * getUpdateAttr<p>
     * GetUpdateAttr<br>
     *     Use GetUpdateAttr when you want to retrieve the new value of an<br>
     *     attribute from a BusinessQuery's Values stack based upon the attribute's<br>
     *     attribute index.  For an insert this will be the value being inserted,<br>
     *     for an update this will be the new value to which the attribute will<br>
     *     be set.<br>
     * <p>
     *     attr<br>
     *       An index identifying which attribute to return.  There is a<br>
     *       constant for each attribute of the entity.  If the attribute<br>
     *       requested has not been updated (i.e. no LogAttr has been done)<br>
     *       then a NIL object will be returned.<br>
     * <p>
     * @param attr Type: int
     * @return DataValue
     */
    public DataValue getUpdateAttr(int attr) {
        if (this.getValues() != null) {
            for (int i = this.getValues().getStack().size(); i >= 2; i--) {
                if (this.getValues().getStack().get(i-1) instanceof ConstraintAttr && (((ConstraintAttr)(this.getValues().getStack().get(i-1))).getAttr() == attr) && this.getValues().getStack().get(i-1-1) instanceof ConstraintValue) {
                    return ((ConstraintValue)(this.getValues().getStack().get(i-1-1))).getValue();
                }
            }
        }

        return null;
    }

    /**
     * hasAttr<p>
     * HasAttr<br>
     *     The HasAttr method returns TRUE if the attribute indicated by the attr<br>
     *     parameter has been selected with the AddAttr method and FALSE otherwise.<br>
     *     If the attr parameter is 0 then HasAttr returns TRUE if any attribute<br>
     *     has been selected.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index indicating which attribute<br>
     *       to check.  If attr is 0 then HasAttr checks for any attribute.<br>
     * <p>
     * @param attr Type: int (Input) (default in Forte: 0)
     * @return boolean
     */
    public boolean hasAttr(int attr) {
        if (attr < 0) {

            throw new Error(Error.BQ_ILLEGAL_ATTR, "HasAttr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (attr == 0) {

            if (this.getTargetAttrs() != null) {
                for (IntegerData i : this.getTargetAttrs()) {
                    if (i.getValue() > 0) {
                        return true;
                    }
                }
            }

        }
        else if (attr < BusinessQuery.ATTR_FOREIGN) {

            int wordindex = (attr-1)/31+1;
            int bitmask = (int)new DoubleData().power(2, attr-(wordindex-1)*31-1).getValue();

            if (this.getTargetAttrs() != null) {
                if (wordindex <= this.getTargetAttrs().size()) {
                    if ((this.getTargetAttrs().get(wordindex-1).getValue()&bitmask) > 0) {
                        return true;
                    }
                }
            }

        }
        else {

            if (this.getForeignClasses() != null) {
                for (BusinessQuery f : this.getForeignClasses()) {
                    if (f.getParentAttr() == attr) {
                        return true;
                    }
                }
            }

        }

        return false;
    }

    /**
     * newArray<p>
     * NewArray<br>
     *     The NewArray method is used by the SQLselect method when new<br>
     *     BusinessClass arrays of the custom subclass need to be created.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     Returns<br>
     *       A new BusinessClass array of the custom subclass.<br>
     * <p>
     * @return Array_Of_BusinessClass<BusinessClass>
     */
    public Array_Of_BusinessClass<BusinessClass> newArray() {
        throw new Error(Error.GEN_UNIMPLEMENTED, "NewArray", this).getException();
    }

    /**
     * newClass<p>
     * NewClass<br>
     *     The NewClass method is used by the SQLselect method when new<br>
     *     BusinessClasses of the custom subclass need to be created.<br>
     * <p>
     *     This method will be overridden by the query's generated class.<br>
     * <p>
     *     Returns<br>
     *       A new BusinessClass of the custom subclass.<br>
     * <p>
     * @return BusinessClass
     */
    public BusinessClass newClass() {
        throw new Error(Error.GEN_UNIMPLEMENTED, "NewClass", this).getException();
    }

    /**
     * newQuery<p>
     * NewQuery<br>
     *     The NewQuery method is used to create a BusinessQuery for<br>
     *     the foreign attribute specified by the attr parameter.<br>
     * <p>
     *     attr<br>
     *       The attr parameter specifies which kind of BusinessQuery should be<br>
     *       returned.  It should be for a foreign BusinessClass.<br>
     * <p>
     *     Returns<br>
     *       The return value is the BusinessQuery for the attribute specified<br>
     *       by the attr parameter.<br>
     * <p>
     * @param attr Type: int (Input) (default in Forte: 0)
     * @return BusinessQuery
     */
    public BusinessQuery newQuery(int attr) {
        throw new Error(Error.GEN_UNIMPLEMENTED, "NewQuery", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
    }
    /**
     * Same as {@link #newQuery(int) with default value.
     * @return
     */
    public BusinessQuery newQuery() {
      return newQuery(0);
    }

    /**
     * processJoins<p>
     * <p>
     */
    public void processJoins() {
        if ((this.getExecuteInfo().getStatus()&QueryExecuteInfo.ST_BUILT) > 0) {
            return;
        }

        //
        //  Check for 1-1 associations
        //
        if (this.getForeignClasses() != null) {
            for (BusinessQuery fe : this.getForeignClasses()) {
                if ((fe.getParentMult()&BusinessQuery.ASSOC_MULT_TO_ONE) > 0) {
                    if (fe.getConstraint() == null || fe.getConstraint().getOperation(ConstraintOperation.OP_NO_JOIN) == 0) {
                        //
                        // Let's join it!
                        //
                        fe.getExecuteInfo().setStatus(fe.getExecuteInfo().getStatus()|QueryExecuteInfo.ST_JOINED);
                        fe.getExecuteInfo().setSqlQuery(this.getExecuteInfo().getSqlQuery());
                        fe.processJoins();
                    }
                }
            }
        }

        //
        //  Check for optional associations
        //
        if ((this.getExecuteInfo().getSqlQuery().getOptions()&SqlQuery.OPT_NO_OUTER_JOIN) == 0) {
            if (this.getForeignClasses() != null) {
                checkOptionalAssoc:
                for (BusinessQuery fe : this.getForeignClasses()) {
                    if ((fe.getParentMult()&BusinessQuery.ASSOC_MULT_OPTIONAL) > 0 && (fe.getConstraint() == null || fe.getConstraint().getOperation(ConstraintOperation.OP_NO_JOIN) == 0)) {
                        // 
                        //  Need to check that the foreign class doesn't do a
                        //  one-to-one association with another class.  If it
                        //  does we don't want to process it now.  We'll wait
                        //  and get the two foreign classes done together when
                        //  SelectForeign is called.
                        //
                        Array_Of_BusinessQuery<BusinessQuery> qq_localVector = fe.getForeignClasses();
                        if (qq_localVector != null) {
                            for (BusinessQuery fefe : qq_localVector) {
                                if ((fefe.getParentMult()&BusinessQuery.ASSOC_MULT_TO_ONE) > 0) {
                                    continue checkOptionalAssoc;
                                }
                            }
                        }
                        //
                        // Let's join it!
                        //
                        fe.getExecuteInfo().setStatus(fe.getExecuteInfo().getStatus()|QueryExecuteInfo.ST_JOINED);
                        fe.getExecuteInfo().setSqlQuery(this.getExecuteInfo().getSqlQuery());
                        //
                        //  If we can handle transitive outer joins (one table outer
                        //  joined to another which is, in turn, outer joined to
                        //  another) then go do those.
                        //
                        if ((this.getExecuteInfo().getSqlQuery().getOptions()&SqlQuery.OPT_NO_TRANSITIVE_OUTER_JOIN) == 0) {
                            fe.processJoins();
                        }
                    }
                }
            }
        }
    }

    /**
     * removeAttr<p>
     * RemoveAttr<br>
     *     The RemoveAttr method is used to remove attributes previously specified<br>
     *     which should no longer be returned in a BusinessClass.  This is the<br>
     *     inverse of AddAttr.  If the attribute requested is a foreign<br>
     *     BusinessClass then the BusinessQuery originally used in the AddAttr<br>
     *     for this attribute must be provided.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index which specifies an<br>
     *       attribute which should be removed.<br>
     * <p>
     * @param attr Type: int
     */
    public void removeAttr(int attr) {
        if (attr < BusinessQuery.ATTR_FOREIGN) {

            //
            //  It is a simple attribute, just add it to the TargetAttrs array.
            //

            if (attr < 0) {

                throw new Error(Error.BQ_ILLEGAL_ATTR, "RemoveAttr", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
            else if (attr == BusinessQuery.ATTR_SIMPLE) {

                this.setTargetAttrs(null);

            }
            else {

                int row = (attr-1)/31+1;
                int mask = (int)new DoubleData(2).power((attr-1) % 31).getValue();
                if (row <= this.getTargetAttrs().size()) {
                    this.getTargetAttrs().get(row-1).setValue(this.getTargetAttrs().get(row-1).getValue()&~mask);
                }

            }

        }
        else {
            //
            //  It is a foreign attribute.
            // 
            if (this.getForeignClasses() != null) {


              for (Iterator<BusinessQuery> iterator = this.getForeignClasses().iterator(); iterator
            .hasNext();) {
                BusinessQuery businessQuery = (BusinessQuery) iterator.next();
                    if (businessQuery.getParentAttr() == attr) {
                        this.getForeignClasses().deleteRow(businessQuery);
                        return;
                    }
        }
            }

        }
    }

    /**
     * reset<p>
     * Reset<br>
     *     The Reset method is used to clear the constraint for a BusinessQuery<br>
     *     which is used for a select.<br>
     * <p>
     */
    public void reset() {
        if (this.operation != BusinessQuery.OP_SELECT) {
            throw new Error(Error.BQ_CANT_RESET, "Reset", this).getException();
        }
        else {
            this.setConstraint(null);
        }
    }

    /**
     * returnSqlQuery<p>
     * <p>
     * @param dBSession Type: DBConnectionManager (Input) (default in Forte: NIL)
     * @return SqlQuery
     */
    public SqlQuery returnSqlQuery(DBConnectionManager dBSession) {
        if (this.getExecuteInfo().getSqlQuery() == null) {
            this.getExecuteInfo().setSqlQuery(this.getSqlQuery(dBSession));
        }

        return this.getExecuteInfo().getSqlQuery();
    }

    /**
     * sendClassOnUpdate<p>
     * SendClassOnUpdate<br>
     *     The SendClassOnUpdate method returns TRUE if the updated BusinessClass<br>
     *     should be sent to the BusinessMgr on an Update request, and FALSE if it<br>
     *     should not.  Normally only a BusinessQuery describing how to change<br>
     *     the underlying database to track the changes made to the BusinessClass<br>
     *     is sent to the BusinessMgr.  If SendClassOnUpdate option was requested<br>
     *     in the business model for this class then this method will be<br>
     *     overridden in the generated class with one which returns TRUE.<br>
     * <p>
     * @return boolean
     */
    public boolean sendClassOnUpdate() {
        return false;
    }

    /**
     * setAttrs<p>
     * SetAttrs<br>
     *     The SetAttrs method is used to set the attributes of a BusinessClass<br>
     *     from the data returned in a dataset by the database.<br>
     * <p>
     *     SetAttrs invokes itself recursively to set attributes in foreign<br>
     *     entities.<br>
     * <p>
     *     NOTE:  You don't normally need to call this method directly, the<br>
     *     BusinessMgr's Select method uses it.<br>
     * <p>
     *     source<br>
     *       The source parameter specifies the BusinessClass whose attributes<br>
     *       should be set.<br>
     * <p>
     *     data<br>
     *       The data paramters contains the data returned from the database.<br>
     * <p>
     *     index<br>
     *       The index parameter specifies which column in the data parameter<br>
     *       was last retrieved.  To retrieve the next value we always increment<br>
     *       the index.<br>
     * <p>
     * @param source Type: BusinessClass
     * @param data Type: DBDataSet
     * @param index Type: int
     */
    public void setAttrs(BusinessClass source, DBDataSet data, ParameterHolder_integer index) {
        int attrs = 0;
        int attrIndex = 0;
        int baseIndex = 1;
        int lNumDBAttrs = this.getNumDBAttrs();
        // local copy of virtual attribute

        if (this.getTargetAttrs() != null) {
            for (IntegerData attr : this.getTargetAttrs()) {
                attrs = attr.getValue();
                attrIndex = baseIndex;
                while ((attrs > 0) && (attrIndex <= lNumDBAttrs)) {
                    if ((attrs&1) > 0) {
                        index.setInt(index.getInt()+1);
                        // TF:Aug 13, 2008:Refactored this to compensate for the case where the string is NULL. This
                        // throws an exception if you set null on a doublenullable for instance, but doesn't seem to
                        // in the Forte DB.setValue() method
                        //source.newAttr(attrIndex).setValue(data.getResultSet().getString(index.getInt()));
                        // AD:12/11/2008: Kintetsu needs to keep the same scale if it is a DecimalData as the source
                        // Added the Below condition to over come the rounding issue if the attribute is of type MoneyDomain. Becuase by default
                        // the values are getting round to the default scale.
                        if(source.newAttr(attrIndex) instanceof DecimalData){
                          ((DecimalData)source.newAttr(attrIndex)).setValue(data.getResultSet().getDataValue(index.getInt()), true);
                        }else{
                          source.newAttr(attrIndex).setValue(data.getResultSet().getDataValue(index.getInt()));
                        }
                        // Mouli - 01, Oct - End
                    }
                    attrs = attrs/2;
                    attrIndex = attrIndex+1;
                }
                baseIndex = baseIndex+31;
            }
        }

        //
        //  Set the Key attribute of the BusinessClass from the attributes
        //  which comprise the key.
        //
        source.setKey(false);

        //
        //  And finally we get all requested foreign entities.
        //
        BusinessClass fe = null;

        if (this.getForeignClasses() != null) {
            for (BusinessQuery q : this.getForeignClasses()) {

                if ((q.getExecuteInfo().getStatus()&QueryExecuteInfo.ST_JOINED) > 0) {

                    //
                    //  First instantiate the foreign attribute, this returns us the foreign
                    //  source which will need to have its values filled in.
                    //
                    // ------------------------------
                    // Parameters for call to NewAttr
                    // ------------------------------
                    ParameterHolder_BusinessClass qq_value = new ParameterHolder_BusinessClass();
                    source.newAttr(q.getParentAttr(), qq_value);
                    fe = (BusinessClass)qq_value.getObject();

                    //
                    //  We are now allowing all associated records to be read/write
                    //
                    fe.setInstanceStatus(BusinessClass.ST_READWRITE);

                    //
                    //  SetAttrs on the foreign source will fill it in from where we left off
                    //  (index) in the dataset.
                    //
                    // -------------------------------
                    // Parameters for call to SetAttrs
                    // -------------------------------
                    ParameterHolder_integer qq_index = new ParameterHolder_integer(index.getInt());
                    q.setAttrs(fe, data, qq_index);
                    index.setInt(qq_index.getInt());

                    //
                    //  If this is an optional foreign attribute then we check that the
                    //  record really existed.  If it didn't we delete the class.  We
                    //  make the existance check by looking for a non-NULL key.
                    //
                    if ((q.getParentMult()&BusinessQuery.ASSOC_MULT_OPTIONAL) > 0) {
                        if (fe.getInstanceKey().getValues().size() == 0) {
                            source.setAttr(q.getParentAttr(), (BusinessClass)(null));
                        }
                    }

                }

            }
        }
    }

    /**
     * setOperation<p>
     * SetOperation<br>
     *     The SetOperation method sets operation which this query is<br>
     *     going to perform.  SetOperation should be called before any other<br>
     *     method and should only be used once.  Thus a BusinessQuery can be used<br>
     *     for one and only one operation.<br>
     * <p>
     *     operation<br>
     *       The operation parameter specifies which operation this query<br>
     *       should perform.  Legal values are:  OP_SELECT, OP_INSERT,<br>
     *       OP_UPDATE, or OP_DELETE.<br>
     * <p>
     *     key<br>
     *       The key parameter specifies the key of the BusinessClass which<br>
     *       you are updating.  The key parameter should be passed for the<br>
     *       operations:  OP_INSERT, OP_UPDATE, or OP_DELETE, but should not<br>
     *       be passed for OP_SELECT operations.<br>
     * <p>
     * @param operation Type: int
     * @param key Type: BusinessKey (Input) (default in Forte: NIL)
     */
    public void setOperation(int operation, BusinessKey key) {
        if (operation == this.operation && (key == null || key == this.getKey())) {
            return;
        }

        if ((this.operation != BusinessQuery.OP_SELECT) && (this.operation != BusinessQuery.OP_NONE) && (this.operation != BusinessQuery.OP_UPDATE || operation != BusinessQuery.OP_DELETE)) {

            throw new Error(Error.BQ_CANT_RESET_OP, "SetOperation", this, new IntegerData(this.operation), new IntegerData(operation)).getException();

        }
        else {
            switch (operation) {

                case BusinessQuery.OP_SELECT: {
                    if (key != null) {
                        throw new Error(Error.BQ_SETOP_NO_KEY_ON_SELECT, "SetOperation", this).getException();
                    }

                    break;
                }
                case BusinessQuery.OP_INSERT: {
                    if (key != null) {
                        throw new Error(Error.BQ_SETOP_NO_KEY_ON_INSERT, "SetOperation", this).getException();
                    }

                    break;
                }
                case BusinessQuery.OP_NONE: {
                    if (key != null) {
                        throw new Error(Error.BQ_SETOP_NO_KEY_ON_INSERT, "SetOperation", this).getException();
                    }

                    break;
                }
                case BusinessQuery.OP_DELETE: {
                    if (key == null) {
                        throw new Error(Error.BQ_SETOP_NEED_KEY_FOR_UPDATE, "SetOperation", this).getException();
                    }

                    break;
                }
                case BusinessQuery.OP_UPDATE: {
                    if (key == null) {
                        throw new Error(Error.BQ_SETOP_NEED_KEY_FOR_UPDATE, "SetOperation", this).getException();
                    }

                    break;
                }

                default: {
                    throw new Error(Error.BQ_ILLEGAL_OPERATION, "SetOperation", this).getException();

                }
            }
        }

        this.operation = operation;
        this.setKey(key);
    }
    /**
     * Same as {@link #setOperation()} with default key of null.
     * @param operation
     */
    public void setOperation(int operation) {
      this.setOperation(operation, null);
    }

    /**
     * setValue<p>
     * SetValue<br>
     *     The SetValue method is used to set the values of attributes for<br>
     *     BusinessClasses being updated or inserted.<br>
     * <p>
     *     SetValue pushes the value, attribute, and operation onto the<br>
     *     Values stack.<br>
     * <p>
     *     attr<br>
     *       The attr parameter is an attribute index specifying an attribute<br>
     *       whose value should be set.<br>
     * <p>
     *     value<br>
     *       The value parameter specifies the value to which the attribute<br>
     *       should be set.<br>
     * <p>
     * @param attr Type: int
     * @param value Type: DataValue
     */
    public void setValue(int attr, DataValue value) {
        if (attr > this.getNumAttrs()) {

            throw new Error(Error.BQ_ILLEGAL_ATTR, "SetValue", this, new IntegerData(attr), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if ((this.operation != BusinessQuery.OP_UPDATE) && (this.operation != BusinessQuery.OP_INSERT)) {

            throw new Error(Error.BQ_ILLEGAL_ACTION_FOR_OP, "SetValue", this, new IntegerData(this.operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (this.getValues() == null) {

            this.setValues(new QueryConstraint());

        }

        this.getValues().addValue(value);
        this.getValues().addAttr(this, attr, 1);
        this.getValues().addOperation(ConstraintOperation.OP_EQ);
    }

    /**
     * setValueTemplate<p>
     * SetValueTemplate<br>
     *     Perform a SetValue on "type"; use a template, if one is given.<br>
     * <p>
     * @param type Type: DataValue
     * @param value Type: DataValue
     * @param templateText Type: TextData
     */
    public void setValueTemplate(DataValue type, DataValue value, TextData templateText) {
        if (templateText != null) {
            if (type instanceof DateTimeData) {
                type.decodeValue(value.getTextValue(), new DateFormat(templateText));
            }
            else if (type instanceof NumericData) {
                type.decodeValue(value.getTextValue(), new NumericFormat(templateText));
            }
            else if (type instanceof TextData) {
                type.decodeValue(value.getTextValue(), new TextFormat(templateText, qq_Resolver.cTEMPLATE));
            }
            else {
                type.setValue(value);
            }
        }
        else {
            type.setValue(value);
        }
    }
// end class BusinessQuery
// c Pass 2 Conversion Time: 7016 milliseconds
TOP

Related Classes of Express.services.BusinessQuery

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.