Package Express.services

Source Code of Express.services.SqlQuery

package Express.services;

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

import DisplayProject.binding.beans.ExtendedPropertyChangeSupport;
import DisplayProject.binding.beans.Observable;
import Express.domains.LongTextDomain;
import Framework.Array_Of_DataValue;
import Framework.Array_Of_TextData;
import Framework.CloneHelper;
import Framework.DataValue;
import Framework.IntegerData;
import Framework.ParameterHolder_TextData;
import Framework.ParameterHolder_integer;
import Framework.RuntimeProperties;
import Framework.TextData;
import GenericDBMS.Constants;
import GenericDBMS.DBConnectionManager;

/**
* Builds an SQL query for select, insert, update, or delete operations.
* <p>
* @author ITerative Consulting
* @since  26-Feb-2008
*/
@RuntimeProperties(isDistributed=false, isAnchored=false, isShared=false, isTransactional=false)
@SuppressWarnings("serial")
public class SqlQuery
        implements Serializable, Observable
{

    // ---------
    // Constants
    // ---------
    public static final int ATTRTYPE_CUSTOM = 4;
    public static final int ATTRTYPE_DB = 2;
    public static final int OP_FORMAT_ABS = 9;
    public static final int OP_FORMAT_ADD = 10;
    public static final int OP_FORMAT_AND = 2;
    public static final int OP_FORMAT_BETWEEN = 2;
    public static final int OP_FORMAT_DIV = 10;
    public static final int OP_FORMAT_EQ = 2;
    public static final int OP_FORMAT_EQUIJOIN = 2;
    public static final int OP_FORMAT_GE = 2;
    public static final int OP_FORMAT_GT = 2;
    public static final int OP_FORMAT_IN = 0;
    public static final int OP_FORMAT_LE = 2;
    public static final int OP_FORMAT_LIKE = 2;
    public static final int OP_FORMAT_LT = 2;
    public static final int OP_FORMAT_MUL = 2;
    public static final int OP_FORMAT_NE = 2;
    public static final int OP_FORMAT_NOT = 9;
    public static final int OP_FORMAT_NOTNULL = 4;
    public static final int OP_FORMAT_NULL = 4;
    public static final int OP_FORMAT_OR = 10;
    public static final int OP_FORMAT_RTRIM = 9;
    public static final int OP_FORMAT_SUB = 10;
    public static final int OP_INFIX_MASK = 2;
    public static final int OP_PAREN_MASK = 8;
    public static final int OP_POSTFIX_MASK = 4;
    public static final int OP_PREFIX_MASK = 1;
    public static final int OPT_COLLECTIVE_FOR_ONE = 2;
    public static final int OPT_INNER_JOIN = 4;
    public static final int OPT_JOIN_TYPE = 12;
    public static final int OPT_NO_COLLECTIVE = 1;
    public static final int OPT_NO_MULT_OUTER_JOIN = 64;
    public static final int OPT_NO_OUTER_JOIN = 32;
    public static final int OPT_NO_TRANSITIVE_OUTER_JOIN = 16;
    public static final int OPT_OUTER_JOIN = 8;

    // ----------
    // Attributes
    // ----------
    public PropertyChangeSupport qq_Listeners = new ExtendedPropertyChangeSupport(this, true);
    private Array_Of_TextData<TextData> columnList;
    private Array_Of_SqlData<SqlData> data;
    private DBConnectionManager dBSession;
    private boolean distinct;
    private boolean forUpdate;
    private int maxRows;
    private IntegerData numTables;
    private int operation;
    private TextData orderClause;
    private BusinessQuery query;
    private Array_Of_SqlQueryTable<SqlQueryTable> tableList;
    private Array_Of_TextData<TextData> whereClause;
    private int options;

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

        this.setOperation(0);
        this.setNumTables(new IntegerData());
        this.columnList = new Array_Of_TextData<TextData>();
        this.tableList = new Array_Of_SqlQueryTable<SqlQueryTable>();
        this.setData(new Array_Of_SqlData<SqlData>());
        this.setWhereClause(new Array_Of_TextData<TextData>());

    }

    public SqlQuery(int pOperation) {
        this();
        this.setOperation( pOperation );
    }

    // ----------------------
    // Accessors and Mutators
    // ----------------------
    @SuppressWarnings("unused")
  private void setColumnList(Array_Of_TextData<TextData> columnList) {
        Array_Of_TextData<TextData> oldValue = this.columnList;
        this.columnList = columnList;
        this.qq_Listeners.firePropertyChange("columnList", oldValue, this.columnList);
    }

    /**
   * The GetColumnList method returns the columns previously added by the
   * AddColumn method. For DML (insert, update, delete), each element in the
   * array corresponds to one table. Each element will contain a
   * comma-separated list of column names. For a Select query, one element
   * will be returned. This lone TextData object will contain a
   * comma-separated list of column names qualified by a table alias of the
   * form t<n> where <n> is the number of the table to which it belongs
   *
   * @return
   */
    public Array_Of_TextData<TextData> getColumnList() {
        return this.columnList;
    }

    public void setData(Array_Of_SqlData<SqlData> data) {
        Array_Of_SqlData<SqlData> oldValue = this.data;
        this.data = data;
        this.qq_Listeners.firePropertyChange("data", oldValue, this.data);
    }

    public Array_Of_SqlData<SqlData> getData() {
        return this.data;
    }

    public void setDBSession(DBConnectionManager dBSession) {
        DBConnectionManager oldValue = this.dBSession;
        this.dBSession = dBSession;
        this.qq_Listeners.firePropertyChange("DBSession", oldValue, this.dBSession);
    }

    public DBConnectionManager getDBSession() {
        return this.dBSession;
    }

    public void setDistinct(boolean distinct) {
        boolean oldValue = this.distinct;
        this.distinct = distinct;
        this.qq_Listeners.firePropertyChange("distinct", oldValue, this.distinct);
    }

    public boolean getDistinct() {
        return this.distinct;
    }

    public void setForUpdate(boolean forUpdate) {
        boolean oldValue = this.forUpdate;
        this.forUpdate = forUpdate;
        this.qq_Listeners.firePropertyChange("forUpdate", oldValue, this.forUpdate);
    }

    public boolean getForUpdate() {
        return this.forUpdate;
    }

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

    public int getMaxRows() {
        return this.maxRows;
    }

    public void setNumTables(IntegerData numTables) {
        IntegerData oldValue = this.numTables;
        this.numTables = numTables;
        this.qq_Listeners.firePropertyChange("numTables", oldValue, this.numTables);
    }

    public IntegerData getNumTables() {
        return this.numTables;
    }

    public 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 setOrderClause(TextData orderClause) {
        TextData oldValue = this.orderClause;
        this.orderClause = orderClause;
        this.qq_Listeners.firePropertyChange("orderClause", oldValue, this.orderClause);
    }

    public TextData getOrderClause() {
        return this.orderClause;
    }

    public void setQuery(BusinessQuery query) {
        BusinessQuery oldValue = this.query;
        this.query = query;
        this.qq_Listeners.firePropertyChange("query", oldValue, this.query);
    }

    public BusinessQuery getQuery() {
        return this.query;
    }

    @SuppressWarnings("unused")
  private void setTableList(Array_Of_SqlQueryTable<SqlQueryTable> tableList) {
        Array_Of_SqlQueryTable<SqlQueryTable> oldValue = this.tableList;
        this.tableList = tableList;
        this.qq_Listeners.firePropertyChange("tableList", oldValue, this.tableList);
    }

    @SuppressWarnings("unused")
  private Array_Of_SqlQueryTable<SqlQueryTable> getTableList() {
        return this.tableList;
    }

    public void setWhereClause(Array_Of_TextData<TextData> whereClause) {
        Array_Of_TextData<TextData> oldValue = this.whereClause;
        this.whereClause = whereClause;
        this.qq_Listeners.firePropertyChange("whereClause", oldValue, this.whereClause);
    }

    public Array_Of_TextData<TextData> getWhereClause() {
        return this.whereClause;
    }

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

    public int getOptions() {
        return this.options;
    }

    // -------
    // 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);
    }

    /**
     * addColumn<p>
     * AddColumn<br>
     *     The AddColumn method is used to spcify the name of a column to be<br>
     *     added to the query.  For select querries the column will be put in the<br>
     *     select list, for update querries the column will be put in the set<br>
     *     list, and for insert querries the column will be put into the insert<br>
     *     and values lists.<br>
     * <p>
     *     tableIndex<br>
     *       The tableIndex parameter specifies to which table this column<br>
     *       belongs.<br>
     * <p>
     *     columnName<br>
     *       The columnName parameter holds the name of the column being added.<br>
     * <p>
     *     value<br>
     *       The value parameter holds the value to which this column should be<br>
     *       set.  This is only used for insert and update querries.<br>
     * <p>
     * @param tableIndex Type: int
     * @param columnName Type: TextData
     * @param value Type: DataValue (Input) (default in Forte: NIL)
     */
    public void addColumn(int tableIndex, TextData columnName, DataValue value) {
        if (this.getOperation() == 0) {

            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddColumn", this).getException();

        }
        else if (this.getOperation() == BusinessQuery.OP_SELECT) {

            //
            //  Selects only use the first element of the column list.  Add this
            //  column to the end of it.
            //
            if (this.columnList.get(0).getActualSize() > 0) {
                this.columnList.get(0).concat(", ");
            }
            this.columnList.get(0).concat(new TextData().replaceParameters("t%1.%2", new IntegerData(tableIndex), columnName));

        }
        else if ((this.getOperation() == BusinessQuery.OP_INSERT) || (this.getOperation() == BusinessQuery.OP_UPDATE)) {

            if (this.columnList.get(tableIndex-1).getActualSize() > 0) {
                this.columnList.get(tableIndex-1).concat(", ");
            }

            //
            //  Add this column to the list for the associated table.
            //
            this.columnList.get(tableIndex-1).concat(columnName);

            if (this.getOperation() == BusinessQuery.OP_UPDATE) {

                //
                //  For update the column list is the set clause and we need to add
                //  the '=' and the placeholder to which the value will be bound.
                //
                this.columnList.get(tableIndex-1).concat("=?");

            }

            //
            //  Add the value to the data list.  For insert these values will be
            //  bound to the values clause.  For update they will be bound to the
            //  placeholders we created in the set clause.
            //
            if (value == null) {
                throw new Error(Error.SQL_NEED_VALUE, "AddColumn", this).getException();
            }
            else {
                this.getData().get(tableIndex-1).getValues().add(value);
            }

        }
        else {

            throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddColumn", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
    }
    public void addColumn(int tableIndex, TextData columnName) {
      this.addColumn(tableIndex, columnName, null);
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method adds a constraint to the where clause and<br>
     *     'and's it to the other constraints if there are any.<br>
     * <p>
     *     constraint<br>
     *       The constraint parameter holds the constraint text.<br>
     * <p>
     * @param constraint Type: String
     */
    public void addConstraint(String constraint) {
        if (constraint != null && !("".equals(constraint))) {

            if (this.getWhereClause().get(0).getActualSize() > 0) {
                this.getWhereClause().get(0).concat(" and ");
            }

            this.getWhereClause().get(0).concat(constraint);

        }
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method adds a constraint to the where clause and<br>
     *     'and's it to the other constraints if there are any.<br>
     * <p>
     *     tableIndex<br>
     *       The tableIndex parameter specifies to which table this constraint<br>
     *       applies.<br>
     * <p>
     *     columnName<br>
     *       The columnName parameter specfies the column to project against.<br>
     * <p>
     *     operation<br>
     *       The operation parameter specifies the relationship that the column<br>
     *       should hold to the value.  Legal values are specified by the<br>
     *       ConstraintOperation class.<br>
     * <p>
     *     value<br>
     *       The value parameter holds the value that the column should be<br>
     *       compared against.<br>
     * <p>
     * @param tableIndex Type: int
     * @param columnName Type: TextData
     * @param operation Type: int
     * @param value Type: DataValue
     */
    public void addConstraint(int tableIndex, TextData columnName, int operation, DataValue value) {
        if (operation == 0) {

            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();

        }
        else if (this.getOperation() == BusinessQuery.OP_SELECT) {

            this.addConstraint(new TextData().replaceParameters("t%1.%2%3?", new IntegerData(tableIndex), columnName, this.infixOperator(operation, 1)).toString());

            this.getData().get(0).getValues().add(value);

        }
        else {

            this.addConstraint(tableIndex, new TextData().replaceParameters("%1%2?", columnName, this.infixOperator(operation, 1)).toString());

            this.getData().get(tableIndex-1).getValues().add(value);

        }
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method processes a constraint stack and adds it to<br>
     *     the query.  For select this means turning the consraint stack into<br>
     *     SQL text and adding it to the where clause.  For update the constraint<br>
     *     stack contains the columns and values that need to be used in the set<br>
     *     clause.<br>
     * <p>
     *     constraint<br>
     *       The constraint parameter holds the constraint stack to process.<br>
     * <p>
     * @param constraint Type: QueryConstraint
     */
    public void addConstraint(QueryConstraint constraint) {
        ConstraintNode node = null;
        Array_Of_ConstraintNode<ConstraintNode> stack = null;
        int attrMask = 0;
        int valueCount = 0;
        int tableIndex = 0;

        if (this.getOperation() == 0) {

            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();

        }
        else if (constraint != null && constraint.getStack().size() > 0) {

            stack = new Array_Of_ConstraintNode<ConstraintNode>();
            Array_Of_ConstraintNode<ConstraintNode> qq_localVector = constraint.getStack();
            if (qq_localVector != null) {
                for (ConstraintNode n : qq_localVector) {
                    stack.add(n);
                }
            }


            while (stack.size() > 0) {
                node = stack.get(stack.size()-1);
                int op = 0;

                if (node instanceof ConstraintOperation) {
                    op = ((ConstraintOperation)node).getOperation();
                }
                else {
                    throw new Error(Error.QC_NEED_OPERATION_NODE, "AddConstraint", this).getException();
                }

                if ((op&ConstraintOperation.TYPE_MASK) == 0) {
                    //
                    //  It's a where constraint
                    //
                    attrMask = 0;
                    valueCount = 0;
                    tableIndex = 1;
                    // -----------------------------------
                    // Parameters for call to GetWhereText
                    // -----------------------------------
                    ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask);
                    ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount);
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex);
                    TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
                    attrMask = qq_attrMask.getInt();
                    valueCount = qq_valueCount.getInt();
                    tableIndex = qq_tableIndex.getInt();
                    this.addConstraint(tableIndex, qq_GetWhereText.toString());

                }
                else if (this.getOperation() != BusinessQuery.OP_SELECT) {

                    throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddConstraint", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

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

                    stack.deleteRow(stack.size()- 1);
                    this.setForUpdate(true);

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

                    stack.deleteRow(stack.size()- 1);
                    this.setDistinct(true);

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

                    stack.deleteRow(stack.size()- 1);
                    this.setOptions(SqlQuery.OPT_NO_COLLECTIVE);

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

                    stack.deleteRow(stack.size()- 1);
                    this.setOptions(this.getOptions()&(~(SqlQuery.OPT_NO_COLLECTIVE|SqlQuery.OPT_COLLECTIVE_FOR_ONE)));

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

                    stack.deleteRow(stack.size()- 1);
                    node = stack.get(stack.size()-1);
                    if (!(node instanceof ConstraintValue)) {
                        throw new Error(Error.QC_NEED_VALUE_NODE, "AddConstraint", this).getException();
                    }
                    else {
                        this.setMaxRows(((ConstraintValue)node).getValue().asI4());
                        stack.deleteRow(stack.size()- 1);
                    }

                }
                else if ((op&ConstraintOperation.TYPE_MASK) == ConstraintOperation.TYPE_ORDERBY) {

                    stack.deleteRow(stack.size()- 1);
                    node = stack.get(stack.size()-1);
                    if (!(node instanceof ConstraintAttr)) {
                        throw new Error(Error.QC_NEED_ATTR_NODE, "AddConstraint", this).getException();
                    }
                    else {
                        TextData c = null, oldClause = null;
                        ConstraintAttr attrNode = (ConstraintAttr)node;
                        int t = attrNode.getTableIndex();
                        // ------------------------------------
                        // Parameters for call to GetColumnName
                        // ------------------------------------
                        ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
                        ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                        attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
                        t = qq_tableIndex.getInt();
                        c = (TextData)qq_columnName.getObject();
                        if (this.getOrderClause().getActualSize() > 0) {
                            oldClause = this.getOrderClause();
                            this.setOrderClause(new TextData());
                        }
                        this.getOrderClause().replaceParameters("t%1.%2", new IntegerData(t), c);
                        if (op == ConstraintOperation.OP_ORDERBY_DESC) {
                            this.getOrderClause().concat(" desc");
                        }
                        if (oldClause != null) {
                            this.getOrderClause().concat(", ");
                            this.getOrderClause().concat(oldClause);
                        }
                        stack.deleteRow(stack.size()- 1);
                    }

                }
                else {
                    stack.deleteRow(stack.size()- 1);
                    while (stack.size() > 0 && stack.get(stack.size()-1) instanceof ConstraintOperation) {
                        stack.deleteRow(stack.size()- 1);
                    }

                }

            }

        }
    }

    /**
     * addConstraint<p>
     * AddConstraint<br>
     *     The AddConstraint method adds a constraint to the where clause and<br>
     *     'and's it to the other constraints if there are any.<br>
     * <p>
     *     tableIndex<br>
     *       The tableIndex parameter specifies to which table this constraint<br>
     *       applies.<br>
     * <p>
     *     constraint<br>
     *       The constraint parameter holds the constraint text.<br>
     * <p>
     * @param tableIndex Type: int
     * @param constraint Type: String
     */
    public void addConstraint(int tableIndex, String constraint) {
        if (this.getOperation() == 0) {

            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();

        }
        else if (this.getOperation() == BusinessQuery.OP_SELECT && tableIndex > 1) {

            throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddConstraint", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else if (constraint != null && !("".equals(constraint))) {

            if (this.getWhereClause().get(tableIndex-1).getActualSize() > 0) {
                this.getWhereClause().get(tableIndex-1).concat(" and ");
            }

            this.getWhereClause().get(tableIndex-1).concat(constraint);

        }
    }

    /**
     * addTable<p>
     * AddTable<br>
     *     The AddTable method is used to add database tables to the query being<br>
     *     constructed.  As a side effect a unique integer is returned which<br>
     *     identifies the table and should be used in subsequent references to<br>
     *     the table added (e.g. in AddColumn).  AddTable also initializes the<br>
     *     ColumnList, Data, and WhereClause lists for the table added.  Since<br>
     *     a different query will be created for each table (except in the case<br>
     *     of selects) there must be a separate column list for each one as well<br>
     *     as separate data (for placeholders) and where clause (for key<br>
     *     constraint).<br>
     * <p>
     *     tableName<br>
     *       The tableName parameter holds the name of the database table being<br>
     *       added to the query.<br>
     * <p>
     *     Returns<br>
     *       AddTable returns an Integer object whose value is the number by<br>
     *       which the table added should be referred.<br>
     * <p>
     * @param tableName Type: TextData
     * @return IntegerData
     */
    public IntegerData addTable(TextData tableName) {
        if (this.getOperation() == 0) {
            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddTable", this).getException();
        }

        this.getNumTables().increment();

        if (this.getOperation() != BusinessQuery.OP_SELECT) {
            //
            //  A non-Select (insert, update, delete) operation.  We save the table
            //  name in the next element in the table list, and then initialize each
            //  of the other lists.
            //
            this.columnList.set(this.getNumTables().getValue()-1, new TextData());
            this.getData().set(this.getNumTables().getValue()-1, new SqlData());
            this.getWhereClause().set(this.getNumTables().getValue()-1, new TextData());

        }
        else if (this.tableList.get(0) == null) {
            //
            //  Select can accomodate multiple tables in a single statement so
            //  we only use the first element of the various lists and just append
            //  everything onto them.  We only need to initialize them when the
            //  first table is added.
            //
            this.columnList.set(0, new TextData());
            this.getData().set(0, new SqlData());
            this.getWhereClause().set(0, new TextData());
            this.setOrderClause(new TextData());
        }

        SqlQueryTable sqlTable = new SqlQueryTable();
        sqlTable.setTableName(tableName);
        sqlTable.setTableIndex(this.getNumTables().getValue());
        this.tableList.set(this.getNumTables().getValue()-1, sqlTable);

        return CloneHelper.deepClone(this.getNumTables());
    }

    /**
     * addValue<p>
     * AddValue<br>
     *     The AddValue method adds values for the values clause of an insert<br>
     *     or set clause of an update query.  The values and the columns to which<br>
     *     they apply are described in a constraint stack.<br>
     * <p>
     *     constraint<br>
     *       The constraint parameter holds the constraint stack to process.<br>
     * <p>
     * @param constraint Type: QueryConstraint
     */
    public void addValue(QueryConstraint constraint) {
        Array_Of_ConstraintNode<ConstraintNode> stack = null;

        if (this.getOperation() == 0) {

            throw new Error(Error.SQL_OPERATION_UNINITIALIZED, "AddConstraint", this).getException();

        }
        else if (constraint == null || constraint.getStack().size() <= 0) {

            return;

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

            throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "AddValue", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

        }
        else {

            stack = new Array_Of_ConstraintNode<ConstraintNode>();
            Array_Of_ConstraintNode<ConstraintNode> qq_localVector = constraint.getStack();
            if (qq_localVector != null) {
                for (ConstraintNode n : qq_localVector) {
                    stack.add(n);
                }
            }

            ConstraintNode node1 = null;
            ConstraintValue valueNode = null;
            ConstraintAttr attrNode = null;
            TextData c = null;


            while (stack.size() > 0) {
                node1 = stack.get(stack.size()-1);
                stack.deleteRow(stack.size()- 1);


                while (stack.size() > 0) {
                    if (!(node1 instanceof ConstraintOperation)) {
                        throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
                    }
                    else if (((ConstraintOperation)node1).getOperation() == ConstraintOperation.OP_EQ) {
                        break;
                    }
                    else if (((ConstraintOperation)node1).getOperation() != ConstraintOperation.OP_AND) {
                        throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
                    }

                    node1 = stack.get(stack.size()-1);
                    stack.deleteRow(stack.size()- 1);

                }

                if (stack.size() <= 0) {
                    throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "AddConstraint", this).getException();
                }

                valueNode = null;
                attrNode = null;

                for (int i = 1; i <= 2; i++) {

                    node1 = stack.get(stack.size()-1);
                    stack.deleteRow(stack.size()- 1);

                    if (node1 instanceof ConstraintValue) {

                        if (valueNode == null) {
                            valueNode = (ConstraintValue)node1;
                        }
                        else {
                            throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
                        }

                    }
                    else if (node1 instanceof ConstraintAttr) {

                        if (attrNode == null) {
                            attrNode = (ConstraintAttr)node1;
                        }
                        else {
                            throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();
                        }

                    }
                    else {

                        throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "AddConstraint", this).getException();

                    }

                }

                int t1 = 0;
                for (int i = 1; i <= this.getNumTables().getValue(); i++) {
                    t1 = i;
                    // ------------------------------------
                    // Parameters for call to GetColumnName
                    // ------------------------------------
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t1);
                    ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                    attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
                    t1 = qq_tableIndex.getInt();
                    c = (TextData)qq_columnName.getObject();
                    if (c != null) {
                        //
                        //  Key columns get added for all tables.  Other columns only
                        //  get added for the table to which they apply.
                        //
                        if (t1 != i) {
                            if (i == 1) {
                                this.addColumn(t1, c, valueNode.getValue());
                            }
                            break;
                        }
                        this.addColumn(t1, c, valueNode.getValue());
                    }
                }

            }

        }
    }

    /**
     * clearColumnList<p>
     * ClearColumnList<br>
     *     The ClearColumnList method is used to clear the column list.<br>
     * <p>
     */
    public void clearColumnList() {
        if (this.getOperation() != BusinessQuery.OP_SELECT) {
            throw new Error(Error.SQL_ILLEGAL_FOR_OPERATION, "ClearColumnList", this, new IntegerData(this.getOperation()), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
        }

        this.columnList = new Array_Of_TextData<TextData>();
        this.columnList.set(0, new TextData());
    }

    // Method GetColumnList() : Framework.Array of Framework.TextData skipped because it is replaced by accessor / mutator.
    /**
     * getJoinTableText<p>
     * <p>
     * @param joinTable Type: SqlQueryTable
     * @param text Type: TextData
     */
    public void getJoinTableText(SqlQueryTable joinTable, TextData text) {
        int format = this.operationFormat(joinTable.getJoinOp());

        if ((format&SqlQuery.OP_PREFIX_MASK) > 0) {
            text.concat(this.prefixOperator(joinTable.getJoinOp()));
        }

        text.concat(joinTable.getTableName());
        text.concat(" t");
        text.concat(joinTable.getTableIndex());

        Array_Of_SqlQueryTable<SqlQueryTable> qq_localVector = joinTable.getNextTable();
        if (qq_localVector != null) {
            for (SqlQueryTable toTable : qq_localVector) {

                text.concat(this.infixOperator(joinTable.getJoinOp(), 1));

                if (toTable.getNextTable() == null) {
                    text.concat(toTable.getTableName());
                    text.concat(" t");
                    text.concat(toTable.getTableIndex());
                }
                else {
                    text.concat("(");
                    this.getJoinTableText(toTable, text);
                    text.concat(")");
                }

                if ((format&SqlQuery.OP_POSTFIX_MASK) > 0) {
                    text.concat(this.postfixOperator(joinTable.getJoinOp()));
                }

                if (toTable.getOnClause() != null) {
                    text.concat(" on ");
                    text.concat(toTable.getOnClause());
                }
            }
        }
    }

    /**
     * getTableListText<p>
     * <p>
     * @return TextData
     */
    private TextData getTableListText() {
        TextData str = new TextData();

        if (this.tableList != null) {
            for (SqlQueryTable t : this.tableList) {
                if (t.getPrevTable() == null && t.getNextTable() == null) {
                    str.concat(t.getTableName());
                    str.concat(" t");
                    str.concat(t.getTableIndex());
                    str.concat(", ");
                }
                else if (t.getPrevTable() == null) {
                    if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
                        str.concat("{oj ");
                    }
                    this.getJoinTableText(t, str);
                    if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
                        str.concat(" }");
                    }
                    str.concat(", ");
                }
            }
        }

        str.setOffset(str.totalLength()-2);
        str.truncate();

        if (this.getForUpdate() && this.getDBSession().getDBVendorType() == Constants.DB_VT_SYBASE) {
            str.concat(" holdlock");
        }

        return str;
    }

    /**
     * getText<p>
     * GetText<br>
     *     The GetText method returns the SQL text for the queries described by<br>
     *     this object.  To use SqlQuery, set the Operation attribute from the<br>
     *     operations codes defined by BusinessQuery, then use AddTable,<br>
     *     AddColumn, and AddConstraint to describe the query.  Finally GetText<br>
     *     will give you the text of the SQL needed to execute the query<br>
     *     described.<br>
     * <p>
     *     Returns<br>
     *       The text of the SQL queries described by this object.  For select<br>
     *       queries there will only be one element in the array.  For other<br>
     *       queries there will be one element in the array for each table.<br>
     *       Note:  if no query needs to be run for a given table then that<br>
     *       element in the array will contain an empty string.<br>
     * <p>
     * @return Array_Of_TextData<TextData>
     */
    public Array_Of_TextData<TextData> getText() {
        Array_Of_TextData<TextData> queries = new Array_Of_TextData<TextData>();
        TextData text = null;
        TextData whereText = new TextData();

        Tables:
        for (int i = 1; i <= this.tableList.size(); i++) {

            text = new TextData();
            queries.add(text);

            if (this.columnList.get(i-1).getActualSize() <= 1 && this.getOperation() != BusinessQuery.OP_DELETE) {
                //
                //  If there are no columns specified we don't generate a query for
                //  this table.  The one exception being delete where we never specify
                //  columns anyway.
                //
                continue;
            }

            //
            //  If there is going to be a where clause we need to introduce it.  We
            //  parameterize this since we don't always have a where clause.
            //
            if (this.getWhereClause().get(i-1).getActualSize() > 0) {
                whereText.setValue( " where " );
            }
            else {
                whereText.setValue( "" );
            }

            //
            //  Create the query filling in the column list, table name, etc.
            //
            switch (this.getOperation()) {

                case BusinessQuery.OP_SELECT: {
                    if (this.getDistinct()) {
                        text.replaceParameters("select distinct %1 from %2%3%4", this.columnList.get(i-1), this.getTableListText(), whereText, this.getWhereClause().get(0));
                    }
                    else {
                        text.replaceParameters("select %1 from %2%3%4", this.columnList.get(i-1), this.getTableListText(), whereText, this.getWhereClause().get(0));
                    }
                    if (this.getOrderClause().getActualSize() > 2) {
                        text.concat(" order by ");
                        text.concat(this.getOrderClause());
                    }
                    if (this.getForUpdate() && this.getDBSession().getDBVendorType() != Constants.DB_VT_RDB && this.getDBSession().getDBVendorType() != Constants.DB_VT_SYBASE && this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
                        text.concat(" for update");
                    }
                    break Tables;

                }
                case BusinessQuery.OP_UPDATE: {
                    text.replaceParameters("update %1 set %2%3%4", this.tableList.get(i-1).getTableName(), this.columnList.get(i-1), whereText, this.getWhereClause().get(i-1));

                    break;
                }
                case BusinessQuery.OP_DELETE: {
                    text.replaceParameters("delete from %1%2%3", this.tableList.get(i-1).getTableName(), whereText, this.getWhereClause().get(i-1));

                    break;
                }
                case BusinessQuery.OP_INSERT: {
                    //
                    //  For insert we need to create placeholders for the values
                    //  clause -- one for each column in the column list.
                    //
                    TextData values = new TextData("?");
                    this.columnList.get(i-1).setOffset(0);
                    while (this.columnList.get(i-1).moveToChar(",")) {
                        values.concat(",?");
                        this.columnList.get(i-1).moveNext();
                    }

                    text.replaceParameters("insert into %1(%2) values (%3)", this.tableList.get(i-1).getTableName(), this.columnList.get(i-1), values);

                    break;
                }
            }

        }

        return queries;
    }

    /**
     * getWhereText<p>
     * GetWhereText<br>
     *     The GetWhereText method is used to construct a where clause<br>
     *     for a select statement from a constraint stack.<br>
     * <p>
     *     stack<br>
     *       The stack parameter holds the constraint stack to be decoded.<br>
     * <p>
     * @param stack Type: Array_Of_ConstraintNode<ConstraintNode>
     * @param attrMask Type: int
     * @param valueCount Type: int
     * @param tableIndex Type: int
     * @return TextData
     */
    private TextData getWhereText(Array_Of_ConstraintNode<ConstraintNode> stack, ParameterHolder_integer attrMask, ParameterHolder_integer valueCount, ParameterHolder_integer tableIndex) {
        TextData result = new TextData();
        ConstraintNode node = null;
        int opNodeOp = 0;
        int opNodeOpCode = 0;
        ConstraintAttr attrNode = null;
        int t = 0;
        TextData c = null, c2 = null;
        int initialValueCount = valueCount.getInt();

        if (stack.size() <= 0) {
            throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
        }

        node = stack.get(stack.size()-1);
        stack.deleteRow(stack.size()- 1);

        if (node instanceof ConstraintValue) {

            result.setValue( "?" );
            this.getData().get(tableIndex.getInt()-1).getValues().add(((ConstraintValue)node).getValue());
            valueCount.setInt(valueCount.getInt()+1);

        }
        else if (node instanceof ConstraintAttr) {

            attrNode = (ConstraintAttr)node;
            t = attrNode.getTableIndex();
            // ------------------------------------
            // Parameters for call to GetColumnName
            // ------------------------------------
            ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
            ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
            attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
            t = qq_tableIndex.getInt();
            c = (TextData)qq_columnName.getObject();
            if ((c == null || c.getActualSize() == 0) && (attrNode.getAttr() > attrNode.getEntity().getNumDBAttrs())) {
                attrMask.setInt(attrMask.getInt()|SqlQuery.ATTRTYPE_CUSTOM);
            }
            else {
                attrMask.setInt(attrMask.getInt()|SqlQuery.ATTRTYPE_DB);
            }
            if (this.getOperation() == BusinessQuery.OP_SELECT) {
                result.replaceParameters("t%1.%2", new IntegerData(t), c);
            }
            else {
                result.concat(c);
                tableIndex.setInt(t);
            }

        }
        else if (node instanceof ConstraintConstant) {

            result.setValue( ((ConstraintConstant)node).getValue() );

        }
        else if (node instanceof ConstraintOperation) {

            opNodeOp = ((ConstraintOperation)node).getOperation();
            opNodeOpCode = opNodeOp&ConstraintOperation.OPCODE_MASK;

            if (opNodeOpCode == ConstraintOperation.OPCODE_IN) {

                if (stack.size() < 2) {
                    throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
                }

                result.setValue( "(" );

                if (!(stack.get(stack.size()-1) instanceof ConstraintAttr)) {
                    throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
                }
                else {
                    // -----------------------------------
                    // Parameters for call to GetWhereText
                    // -----------------------------------
                    ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
                    ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
                    TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
                    attrMask.setInt(qq_attrMask.getInt());
                    valueCount.setInt(qq_valueCount.getInt());
                    tableIndex.setInt(qq_tableIndex.getInt());
                    c = qq_GetWhereText;
                }

                while (stack.size() > 1 && stack.get(stack.size()-1) instanceof ConstraintAttr) {
                    c.replaceRange(", ", 0, 0);
                    // -----------------------------------
                    // Parameters for call to GetWhereText
                    // -----------------------------------
                    ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
                    ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
                    TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
                    attrMask.setInt(qq_attrMask.getInt());
                    valueCount.setInt(qq_valueCount.getInt());
                    tableIndex.setInt(qq_tableIndex.getInt());
                    c.replaceRange(qq_GetWhereText, 0, 0);
                }

                result.concat(c);
                result.concat(") in (");

                if (!(stack.get(stack.size()-1) instanceof ConstraintValue)) {
                    throw new Error(Error.QC_NEED_VALUE_NODE, "GetWhereText", this).getException();
                }
                else {
                    result.concat(((ConstraintValue)(stack.get(stack.size()-1))).getValue());
                    stack.deleteRow(stack.size()- 1);
                }
                result.concat(")");

                if (stack.size() > 0 && stack.get(stack.size()-1) instanceof ConstraintSqlData) {
                    Array_Of_DataValue<DataValue> qq_localVector = ((ConstraintSqlData)(stack.get(stack.size()-1))).getData().getValues();
                    if (qq_localVector != null) {
                        for (DataValue d : qq_localVector) {
                            this.getData().get(tableIndex.getInt()-1).getValues().add(d);
                        }
                    }
                    stack.deleteRow(stack.size()- 1);
                }

            }
            else if (opNodeOpCode == ConstraintOperation.OPCODE_LEFTJOIN || opNodeOpCode == ConstraintOperation.OPCODE_RIGHTJOIN || opNodeOpCode == ConstraintOperation.OPCODE_EQUIJOIN) {
                boolean doFancyJoin = opNodeOpCode != ConstraintOperation.OPCODE_EQUIJOIN && this.getDBSession().getDBVendorType() != Constants.DB_VT_ORACLE && this.getDBSession().getDBVendorType() != Constants.DB_VT_SYBASE;
                int oldFromTable = 0, newFromTable = 0, oldToTable = 0, newToTable = 0;
                if (opNodeOpCode == ConstraintOperation.OPCODE_EQUIJOIN) {
                    this.setOptions(this.getOptions()|SqlQuery.OPT_INNER_JOIN);
                }
                else {
                    this.setOptions(this.getOptions()|SqlQuery.OPT_OUTER_JOIN);
                }
                TextData c3 = new TextData();
                if (doFancyJoin) {
                    node = stack.get(stack.size()-1);
                    if (!(node instanceof ConstraintAttr)) {
                        throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
                    }
                    attrNode = (ConstraintAttr)node;
                    if (attrNode.getTableIndex() > this.tableList.size()) {
                        throw new Error(Error.QC_ILLEGAL_TABLE_INDEX, "GetWhereText", this, new IntegerData(attrNode.getTableIndex()), new IntegerData(this.tableList.size())).getException();
                    }
                    node = stack.get(stack.size()-1-1);
                    if (!(node instanceof ConstraintAttr)) {
                        throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
                    }
                    if (((ConstraintAttr)node).getTableIndex() > this.tableList.size()) {
                        throw new Error(Error.QC_ILLEGAL_TABLE_INDEX, "GetWhereText", this, new IntegerData(attrNode.getTableIndex()), new IntegerData(this.tableList.size())).getException();
                    }
                    t = attrNode.getEntity().getTableAliases().get(attrNode.getTableIndex()-1).getValue();
                    int t2 = ((ConstraintAttr)node).getEntity().getTableAliases().get(((ConstraintAttr)node).getTableIndex()-1).getValue();
                    //
                    //  We want to put in a join for attrNode.  We know the table
                    //  aliases t, and t2 to use.  We have to check that these
                    //  tables aren't already participating in a join.  If either of
                    //  them are then we will have to make a new table alias for that
                    //  table and put in an addtional equijoin between the old alias
                    //  and the new based, of course, on the key columns.  The one
                    //  exception is that t can participate in multiple joins if
                    //  the OPT_NO_MULT_OUTER_JOIN option is not set.
                    //
                    int t3 = 0;
                    if (this.tableList.get(t2-1).getPrevTable() != null) {
                        oldToTable = t2;
                        this.addTable(this.tableList.get(t2-1).getTableName());
                        for (int i = 1; i <= attrNode.getEntity().getNumKeyAttrs(); i++) {
                            t3 = attrNode.getTableIndex();
                            // ------------------------------------
                            // Parameters for call to GetColumnName
                            // ------------------------------------
                            ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t3);
                            ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                            attrNode.getEntity().getColumnName(i, qq_tableIndex, qq_columnName);
                            t3 = qq_tableIndex.getInt();
                            c = (TextData)qq_columnName.getObject();
                            if (c == null) {
                                c = new TextData();
                            }
                            this.addConstraint(c3.replaceParameters("t%1.%2 = t%3.%2", new IntegerData(t2), c, this.getNumTables()).toString());
                        }
                        t2 = this.getNumTables().getValue();
                        newToTable = t2;
                    }
                    if (this.tableList.get(t-1).getNextTable() == null) {
                        this.tableList.get(t-1).setNextTable(new Array_Of_SqlQueryTable<SqlQueryTable>());
                        this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
                        this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
                    }
                    else if ((this.getOptions()&SqlQuery.OPT_NO_MULT_OUTER_JOIN) == 0) {
                        this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
                        this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
                    }
                    else {
                        oldFromTable = t;
                        this.addTable(this.tableList.get(t-1).getTableName());
                        for (int i = 1; i <= attrNode.getEntity().getNumKeyAttrs(); i++) {
                            t3 = attrNode.getTableIndex();
                            // ------------------------------------
                            // Parameters for call to GetColumnName
                            // ------------------------------------
                            ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t3);
                            ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                            attrNode.getEntity().getColumnName(i, qq_tableIndex, qq_columnName);
                            t3 = qq_tableIndex.getInt();
                            c = (TextData)qq_columnName.getObject();
                            if (c == null) {
                                c = new TextData();
                            }
                            this.addConstraint(c3.replaceParameters("t%1.%2 = t%3.%2", new IntegerData(t), c, this.getNumTables()).toString());
                        }
                        t = this.getNumTables().getValue();
                        newFromTable = t;
                        this.tableList.get(t-1).setNextTable(new Array_Of_SqlQueryTable<SqlQueryTable>());
                        this.tableList.get(t-1).getNextTable().add(this.tableList.get(t2-1));
                        this.tableList.get(t2-1).setPrevTable(this.tableList.get(t-1));
                    }
                    this.tableList.get(t-1).setJoinOp(opNodeOpCode);
                    if (this.getDBSession().getDBVendorType() != Constants.DB_VT_INFORMIX) {
                        this.tableList.get(t2-1).setOnClause(result);
                    }
                }
                //
                //   We've now completed linking the joined tables together in the
                //   table list.  Now we need to create the join condition.  Depending
                //   on the database this may end up in the where clause or in the
                //   join clause.
                //
                int params = (opNodeOp&ConstraintOperation.PCOUNT_MASK)/ConstraintOperation.PCOUNT_INCREMENT;
                if (stack.size() < params*2) {
                    throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
                }
                int format = this.operationFormat(opNodeOp);
                if (doFancyJoin) {
                    c2 = new TextData(" = ");
                }
                else {
                    c2 = this.infixOperator(opNodeOp, 1);
                }
                for (int i = 1; i <= params*2; i++) {
                    if (i > 1) {
                        if ((i&1) > 0) {
                            result.concat(" and ");
                        }
                        else {
                            result.concat(c2);
                        }
                    }
                    node = stack.get(stack.size()-1);
                    if (!(node instanceof ConstraintAttr)) {
                        throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
                    }
                    stack.deleteRow(stack.size()- 1);
                    attrNode = (ConstraintAttr)node;
                    t = attrNode.getTableIndex();
                    // ------------------------------------
                    // Parameters for call to GetColumnName
                    // ------------------------------------
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(t);
                    ParameterHolder_TextData qq_columnName = new ParameterHolder_TextData();
                    attrNode.getEntity().getColumnName(attrNode.getAttr(), qq_tableIndex, qq_columnName);
                    t = qq_tableIndex.getInt();
                    c = (TextData)qq_columnName.getObject();
                    if (t == oldFromTable) {
                        t = newFromTable;
                    }
                    else if (t == oldToTable) {
                        t = newToTable;
                    }
                    if (c == null) {
                        c = new TextData();
                    }
                    result.concat(c3.replaceParameters("t%1.%2", new IntegerData(t), c));
                    if ((i&1) == 0 && (format&SqlQuery.OP_POSTFIX_MASK) > 0) {
                        result.concat(this.postfixOperator(opNodeOp));
                    }
                }
                if (doFancyJoin && this.getDBSession().getDBVendorType() != Constants.DB_VT_INFORMIX) {
                    result = new TextData();
                }

            }
            else if (opNodeOpCode == ConstraintOperation.OPCODE_APPROX) {

                ConstraintValue valueNode = null;
                QueryConstraint constraint = new QueryConstraint();
                constraint.setStack(stack);

                if (stack.size() < 2) {
                    throw new Error(Error.QC_CONSTRAINT_STACK_EMPTY, "GetWhereText", this).getException();
                }

                if (!(stack.get(stack.size()-1) instanceof ConstraintAttr)) {
                    throw new Error(Error.QC_NEED_ATTR_NODE, "GetWhereText", this).getException();
                }
                else {
                    attrNode = (ConstraintAttr)(stack.get(stack.size()-1));
                    stack.deleteRow(stack.size()- 1);
                }

                if (!(stack.get(stack.size()-1) instanceof ConstraintValue)) {
                    throw new Error(Error.QC_NEED_VALUE_NODE, "GetWhereText", this).getException();
                }
                else {
                    valueNode = (ConstraintValue)(stack.get(stack.size()-1));
                    stack.deleteRow(stack.size()- 1);
                }

                if (attrNode.getAttr() > attrNode.getEntity().getNumDBAttrs()) {
                    //   Custom attribute -- skip it.
                    return result;
                }

                int dtype = valueNode.getValue().dataType()&127;

                if (dtype == 6) {
                    // value.IsA(TextData)
                    if (!(valueNode.getValue() instanceof LongTextDomain)) {
                        TextData v = (TextData)valueNode.getValue();
                        if (v.getIsNull()) {
                            stack.add(attrNode);
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
                        }
                        else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB || this.getDBSession().getDBVendorType() == Constants.DB_VT_DB2) {
                            stack.add(valueNode);
                            stack.add(attrNode);
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
                        }
                        else if (v.getActualSize() == 0) {
                            constraint.addConstant(new TextData("' '"));
                            stack.add(attrNode);
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
                            stack.add(attrNode);
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_OR));
                        }
                        else {
                            stack.add(valueNode);
                            stack.add(attrNode);
                            v.setOffset(v.getActualSize()-1);
                            if (!(v.isChar(" "))) {
                                stack.add(new ConstraintOperation(ConstraintOperation.OP_RTRIM));
                            }
                            stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));
                        }
                    }

                }
                else if (dtype == 8 || dtype == 9) {
                    // if value.IsA(BinaryData) or value.IsA(ImageData) leave it out of the
                    // constraint.

                }
                else if (dtype == 7 || dtype == 1) {
                    // value.IsA(DoubleData)
                    if (valueNode.getValue().getIsNull()) {
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));
                    }
                    else if (this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
                        constraint.addConstant(new TextData(".000000000001"));
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_ABS));
                        stack.add(valueNode);
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_ABS));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
                    }
                    else {
                        constraint.addConstant(new TextData(".000000000001"));
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
                        stack.add(valueNode);
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
                        constraint.addConstant(new TextData(".000000000001"));
                        stack.add(attrNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_MUL));
                        stack.add(attrNode);
                        stack.add(valueNode);
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_SUB));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_LE));
                        stack.add(new ConstraintOperation(ConstraintOperation.OP_OR));
                    }

                }
                else if (valueNode.getValue().getIsNull()) {
                    stack.add(attrNode);
                    stack.add(new ConstraintOperation(ConstraintOperation.OP_NULL));

                }
                else {
                    stack.add(valueNode);
                    stack.add(attrNode);
                    stack.add(new ConstraintOperation(ConstraintOperation.OP_EQ));

                }

                if (stack.size() > 0) {
                    // -----------------------------------
                    // Parameters for call to GetWhereText
                    // -----------------------------------
                    ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
                    ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
                    TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
                    attrMask.setInt(qq_attrMask.getInt());
                    valueCount.setInt(qq_valueCount.getInt());
                    tableIndex.setInt(qq_tableIndex.getInt());
                    result = qq_GetWhereText;
                }

            }
            else {
                int format = this.operationFormat(opNodeOp);
                if ((format&SqlQuery.OP_PREFIX_MASK) > 0) {
                    result = this.prefixOperator(opNodeOp);
                }
                if ((opNodeOp&ConstraintOperation.PCOUNT_MASK) > 0) {
                    if ((format&SqlQuery.OP_PAREN_MASK) > 0) {
                        result.concat("(");
                    }
                    // -----------------------------------
                    // Parameters for call to GetWhereText
                    // -----------------------------------
                    ParameterHolder_integer qq_attrMask = new ParameterHolder_integer(attrMask.getInt());
                    ParameterHolder_integer qq_valueCount = new ParameterHolder_integer(valueCount.getInt());
                    ParameterHolder_integer qq_tableIndex = new ParameterHolder_integer(tableIndex.getInt());
                    TextData qq_GetWhereText = this.getWhereText(stack, qq_attrMask, qq_valueCount, qq_tableIndex);
                    attrMask.setInt(qq_attrMask.getInt());
                    valueCount.setInt(qq_valueCount.getInt());
                    tableIndex.setInt(qq_tableIndex.getInt());
                    result.concat(qq_GetWhereText);
                    for (int i = 2; i <= (opNodeOp&ConstraintOperation.PCOUNT_MASK)/ConstraintOperation.PCOUNT_INCREMENT; i++) {
                        if ((format&SqlQuery.OP_INFIX_MASK) > 0) {
                            result.concat(this.infixOperator(opNodeOp, i-1));
                        }
                        else {
                            result.concat(", ");
                        }
                        // -----------------------------------
                        // Parameters for call to GetWhereText
                        // -----------------------------------
                        ParameterHolder_integer qq_attrMask1 = new ParameterHolder_integer(attrMask.getInt());
                        ParameterHolder_integer qq_valueCount1 = new ParameterHolder_integer(valueCount.getInt());
                        ParameterHolder_integer qq_tableIndex1 = new ParameterHolder_integer(tableIndex.getInt());
                        TextData qq_GetWhereText1 = this.getWhereText(stack, qq_attrMask1, qq_valueCount1, qq_tableIndex1);
                        attrMask.setInt(qq_attrMask1.getInt());
                        valueCount.setInt(qq_valueCount1.getInt());
                        tableIndex.setInt(qq_tableIndex1.getInt());
                        result.concat(qq_GetWhereText1);
                    }
                    if ((format&SqlQuery.OP_PAREN_MASK) > 0) {
                        result.concat(")");
                    }
                }
                if ((format&SqlQuery.OP_POSTFIX_MASK) > 0) {
                    result.concat(this.postfixOperator(opNodeOp));
                }

            }

            if ((attrMask.getInt()&SqlQuery.ATTRTYPE_CUSTOM) > 0) {
                if ((attrMask.getInt()&SqlQuery.ATTRTYPE_DB) > 0) {
                    throw new Error(Error.QC_CUSTOM_AND_DB_ATTR, "GetWhereText", this, result, Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }
                result.clear();
                for (int i = initialValueCount+1; i <= valueCount.getInt(); i++) {
                    this.getData().get(tableIndex.getInt()-1).getValues().deleteRow(this.getData().get(tableIndex.getInt()-1).getValues().size()- 1);
                }
                valueCount.setInt(initialValueCount);
            }

        }
        else {

            throw new Error(Error.QC_ILLEGAL_CONSTRAINT_NODE, "GetWhereText", this).getException();

        }

        return result;
    }

    /**
     * infixOperator<p>
     * InfixOperator<br>
     *     The InfixOperator method returns the SQL text for the operator specified<br>
     *     by the operation parameter.<br>
     * <p>
     *   operation<br>
     *     The operation parameter specifies which operation for which to return<br>
     *     SQL text.  Legal values are defined by the ConstraintOperation class.<br>
     * <p>
     * @param operation Type: int
     * @param position Type: int (Input) (default in Forte: 1)
     * @return TextData
     */
    private TextData infixOperator(int operation, int position) {
        TextData result = new TextData();

        switch (operation&ConstraintOperation.OPCODE_MASK) {

            case ConstraintOperation.OPCODE_ADD: {
                result.setValue( " + " );

                break;
            }
            case ConstraintOperation.OPCODE_AND: {
                result.setValue( " and " );

                break;
            }
            case ConstraintOperation.OPCODE_DIV: {
                result.setValue( " / " );

                break;
            }
            case ConstraintOperation.OPCODE_EQ: {
                result.setValue( " = " );

                break;
            }
            case ConstraintOperation.OPCODE_EQUIJOIN: {
                result.setValue( " = " );

                break;
            }
            case ConstraintOperation.OPCODE_GE: {
                result.setValue( " >= " );

                break;
            }
            case ConstraintOperation.OPCODE_GT: {
                result.setValue( " > " );

                break;
            }
            case ConstraintOperation.OPCODE_LE: {
                result.setValue( " <= " );

                break;
            }
            case ConstraintOperation.OPCODE_LT: {
                result.setValue( " < " );

                break;
            }
            case ConstraintOperation.OPCODE_NE: {
                result.setValue( " <> " );

                break;
            }
            case ConstraintOperation.OPCODE_OR: {
                result.setValue( " or " );

                break;
            }
            case ConstraintOperation.OPCODE_LIKE: {
                result.setValue( " like " );

                break;
            }
            case ConstraintOperation.OPCODE_MUL: {
                result.setValue( " * " );

                break;
            }
            case ConstraintOperation.OPCODE_SUB: {
                result.setValue( " - " );

                break;
            }
            case ConstraintOperation.OPCODE_BETWEEN: {
                if (position == 1) {
                    result.setValue( " between " );
                }
                else {
                    result.setValue( " and " );
                }

                break;
            }
            case ConstraintOperation.OPCODE_LEFTJOIN: {
                switch (this.getDBSession().getDBVendorType()) {
                    case Constants.DB_VT_SYBASE: {
                        result.setValue( " *= " );
                        break;
                    }
                    case Constants.DB_VT_ORACLE: {
                        result.setValue( " = " );
                        break;
                    }
                    case Constants.DB_VT_RDB: {
                        result.setValue( " left outer join " );
                        break;
                    }
                    case Constants.DB_VT_INFORMIX: {
                        result.setValue( ", outer " );
                        break;
                    }
                    case Constants.DB_VT_INGRES: {
                        result.setValue( " left join " );
                        break;
                    }
                    case Constants.DB_VT_ODBC: {
                        result.setValue( " left outer join " );
                        break;
                    }

                    default: {
                        throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                }

                break;
            }
            case ConstraintOperation.OPCODE_RIGHTJOIN: {
                switch (this.getDBSession().getDBVendorType()) {
                    case Constants.DB_VT_SYBASE: {
                        result.setValue( " =* " );
                        break;
                    }
                    case Constants.DB_VT_ORACLE: {
                        result.setValue( " (+) = " );
                        break;
                    }
                    case Constants.DB_VT_RDB: {
                        result.setValue( " right outer join " );
                        break;
                    }
                    case Constants.DB_VT_INFORMIX: {
                        result.setValue( ", " );
                        break;
                    }
                    case Constants.DB_VT_INGRES: {
                        result.setValue( " right join " );
                        break;
                    }
                    case Constants.DB_VT_ODBC: {
                        result.setValue( " right outer join " );
                        break;
                    }

                    default: {
                        throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                    }
                }


                break;
            }

            default: {
                throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "InfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
        }

        return result;
    }

    /**
     * operationFormat<p>
     * <p>
     * @param operation Type: int
     * @return int
     */
    private int operationFormat(int operation) {
        int format = 0;

        switch (operation&ConstraintOperation.OPCODE_MASK) {

            case ConstraintOperation.OPCODE_ADD: {
                format = SqlQuery.OP_FORMAT_ADD;

                break;
            }
            case ConstraintOperation.OPCODE_AND: {
                format = SqlQuery.OP_FORMAT_AND;

                break;
            }
            case ConstraintOperation.OPCODE_DIV: {
                format = SqlQuery.OP_FORMAT_DIV;

                break;
            }
            case ConstraintOperation.OPCODE_EQ: {
                format = SqlQuery.OP_FORMAT_EQ;

                break;
            }
            case ConstraintOperation.OPCODE_EQUIJOIN: {
                format = SqlQuery.OP_FORMAT_EQUIJOIN;

                break;
            }
            case ConstraintOperation.OPCODE_GE: {
                format = SqlQuery.OP_FORMAT_GE;

                break;
            }
            case ConstraintOperation.OPCODE_GT: {
                format = SqlQuery.OP_FORMAT_GT;

                break;
            }
            case ConstraintOperation.OPCODE_LE: {
                format = SqlQuery.OP_FORMAT_LE;

                break;
            }
            case ConstraintOperation.OPCODE_LT: {
                format = SqlQuery.OP_FORMAT_LT;

                break;
            }
            case ConstraintOperation.OPCODE_NE: {
                format = SqlQuery.OP_FORMAT_NE;

                break;
            }
            case ConstraintOperation.OPCODE_OR: {
                format = SqlQuery.OP_FORMAT_OR;

                break;
            }
            case ConstraintOperation.OPCODE_LIKE: {
                format = SqlQuery.OP_FORMAT_LIKE;

                break;
            }
            case ConstraintOperation.OPCODE_MUL: {
                format = SqlQuery.OP_FORMAT_MUL;

                break;
            }
            case ConstraintOperation.OPCODE_NOT: {
                format = SqlQuery.OP_FORMAT_NOT;

                break;
            }
            case ConstraintOperation.OPCODE_NULL: {
                format = SqlQuery.OP_FORMAT_NULL;

                break;
            }
            case ConstraintOperation.OPCODE_NOTNULL: {
                format = SqlQuery.OP_FORMAT_NOTNULL;

                break;
            }
            case ConstraintOperation.OPCODE_SUB: {
                format = SqlQuery.OP_FORMAT_SUB;

                break;
            }
            case ConstraintOperation.OPCODE_BETWEEN: {
                format = SqlQuery.OP_FORMAT_BETWEEN;

                break;
            }
            case ConstraintOperation.OPCODE_LEFTJOIN: {
                format = SqlQuery.OP_INFIX_MASK;
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ORACLE) {
                    format = SqlQuery.OP_INFIX_MASK|SqlQuery.OP_POSTFIX_MASK;
                }

                break;
            }
            case ConstraintOperation.OPCODE_RIGHTJOIN: {
                format = SqlQuery.OP_INFIX_MASK;
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX) {
                    format = SqlQuery.OP_INFIX_MASK|SqlQuery.OP_PREFIX_MASK;
                }

                break;
            }
            case ConstraintOperation.OPCODE_ABS: {
                format = SqlQuery.OP_FORMAT_ABS;

                break;
            }
            case ConstraintOperation.OPCODE_RTRIM: {
                format = SqlQuery.OP_FORMAT_RTRIM;
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
                    format = SqlQuery.OP_PREFIX_MASK|SqlQuery.OP_POSTFIX_MASK;
                }
                else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
                    format = format|SqlQuery.OP_POSTFIX_MASK;
                }

                break;
            }
            case ConstraintOperation.OPCODE_RTRIMFIXED: {
                format = 0;
                if (this.getDBSession().getDBVendorType() != Constants.DB_VT_RDB && this.getDBSession().getDBVendorType() != Constants.DB_VT_DB2) {
                    format = this.operationFormat(ConstraintOperation.OPCODE_RTRIM);
                }

                break;
            }

            default: {
                throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "OperationFormat", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
        }

        return format;
    }

    /**
     * postfixOperator<p>
     * PostfixOperator<br>
     *     The PostfixOperator method returns the SQL text for the operator specified<br>
     *     by the operation parameter.<br>
     * <p>
     *   operation<br>
     *     The operation parameter specifies which operation for which to return<br>
     *     SQL text.  Legal values are defined by the ConstraintOperation class.<br>
     * <p>
     * @param operation Type: int
     * @return TextData
     */
    private TextData postfixOperator(int operation) {
        TextData result = new TextData();

        switch (operation&ConstraintOperation.OPCODE_MASK) {

            case ConstraintOperation.OPCODE_RTRIM: {
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
                    result.setValue( ")" );
                }
                else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
                    result.setValue( "}" );
                }
                else {
                    throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }

                break;
            }
            case ConstraintOperation.OPCODE_RTRIMFIXED: {
                result = this.postfixOperator(ConstraintOperation.OPCODE_RTRIM);

                break;
            }
            case ConstraintOperation.OPCODE_NULL: {
                result.setValue( " is null" );

                break;
            }
            case ConstraintOperation.OPCODE_NOTNULL: {
                result.setValue( " is not null" );

                break;
            }
            case ConstraintOperation.OPCODE_LEFTJOIN: {
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ORACLE) {
                    result.setValue( " (+)" );
                }
                else {
                    throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }

                break;
            }

            default: {
                throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PostfixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
        }

        return result;
    }

    /**
     * prefixOperator<p>
     * PrefixOperator<br>
     *     The PrefixOperator method returns the SQL text for the operator specified<br>
     *     by the operation parameter.<br>
     * <p>
     *   operation<br>
     *     The operation parameter specifies which operation for which to return<br>
     *     SQL text.  Legal values are defined by the ConstraintOperation class.<br>
     * <p>
     * @param operation Type: int
     * @return TextData
     */
    private TextData prefixOperator(int operation) {
        TextData result = new TextData();

        switch (operation&ConstraintOperation.OPCODE_MASK) {

            case ConstraintOperation.OPCODE_ABS: {
                result.setValue( "abs" );

                break;
            }
            case ConstraintOperation.OPCODE_RTRIM: {
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX || this.getDBSession().getDBVendorType() == Constants.DB_VT_RDB) {
                    result.setValue( "trim (trailing ' ' from " );
                }
                else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INGRES) {
                    result.setValue( "trim" );
                }
                else if (this.getDBSession().getDBVendorType() == Constants.DB_VT_ODBC) {
                    result.setValue( "{fn rtrim" );
                }
                else {
                    result.setValue( "rtrim" );
                }

                break;
            }
            case ConstraintOperation.OPCODE_RTRIMFIXED: {
                result = this.prefixOperator(ConstraintOperation.OPCODE_RTRIM);

                break;
            }
            case ConstraintOperation.OPCODE_NOT: {
                result.setValue( "not " );

                break;
            }
            case ConstraintOperation.OPCODE_RIGHTJOIN: {
                if (this.getDBSession().getDBVendorType() == Constants.DB_VT_INFORMIX) {
                    result.setValue( "outer " );
                }
                else {
                    throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PrefixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();
                }

                break;
            }

            default: {
                throw new Error(Error.SQL_ILLEGAL_CONSTRAINT_OPERATOR, "PrefixOperator", this, new IntegerData(operation), Error.qq_Resolver.cERROR_METHODNAME_ORIGINATOR_PARAM1).getException();

            }
        }

        return result;
    }

    /**
     * setup<p>
     * <p>
     * @param query Type: BusinessQuery
     * @param operation Type: int
     * @param dbSession Type: DBConnectionManager
     * @return SqlQuery
     */
    public SqlQuery setup(BusinessQuery query, int operation, DBConnectionManager dbSession) {
        this.setQuery(query);
        this.setOperation(operation);
        this.setDBSession(dbSession);

        if (this.getDBSession() != null) {

            int vt = this.getDBSession().getDBVendorType();

            if (vt == Constants.DB_VT_RDB || vt == Constants.DB_VT_ODBC) {
                this.setOptions(SqlQuery.OPT_COLLECTIVE_FOR_ONE);

            }
            else if (vt == Constants.DB_VT_SYBASE) {
                this.setOptions(SqlQuery.OPT_NO_TRANSITIVE_OUTER_JOIN|SqlQuery.OPT_NO_MULT_OUTER_JOIN);

            }
            else if (vt == Constants.DB_VT_DB2) {
                this.setOptions(SqlQuery.OPT_COLLECTIVE_FOR_ONE);

            }
            else if (vt == Constants.DB_VT_ORACLE) {
                this.setOptions(SqlQuery.OPT_NO_MULT_OUTER_JOIN);

            }

        }

        return this;
    }
// end class SqlQuery
// c Pass 2 Conversion Time: 6281 milliseconds
TOP

Related Classes of Express.services.SqlQuery

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.