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