0001: package org.apache.ojb.broker.query;
0002:
0003: /* Copyright 2002-2005 The Apache Software Foundation
0004: *
0005: * Licensed under the Apache License, Version 2.0 (the "License");
0006: * you may not use this file except in compliance with the License.
0007: * You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: import java.util.ArrayList;
0019: import java.util.Collection;
0020: import java.util.Enumeration;
0021: import java.util.HashMap;
0022: import java.util.Iterator;
0023: import java.util.List;
0024: import java.util.Map;
0025: import java.util.Vector;
0026:
0027: import org.apache.ojb.broker.PersistenceBrokerFactory;
0028: import org.apache.ojb.broker.metadata.FieldHelper;
0029: import org.apache.ojb.broker.core.PersistenceBrokerConfiguration;
0030: import org.apache.ojb.broker.util.configuration.ConfigurationException;
0031:
0032: /**
0033: * Persistent Criteria can be used to retrieve sets of objects based on their attributes
0034: * Normally each attribute is ANDed together, an OR can be performed by creating a new
0035: * PersistentCriteria and adding it.
0036: * <P>
0037: * Criteria are used, rather than a simple string, because they can be precompiled for
0038: * efficiency.
0039: *
0040: * This code is based on stuff from
0041: * COBRA - Java Object Persistence Layer
0042: * Copyright (C) 1997, 1998 DB Harvey-George
0043: * eMail: cobra@lowrent.org
0044: *
0045: * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
0046: * @version $Id: Criteria.java,v 1.45.2.5 2005/12/21 22:27:09 tomdz Exp $
0047: */
0048: public class Criteria implements java.io.Serializable {
0049: static final long serialVersionUID = 7384550404778187808L;
0050:
0051: /** criteria is OR-ed with it's parent */
0052: public static final int OR = 0;
0053: /** criteria is AND-ed with it's parent */
0054: public static final int AND = 1;
0055: /** criteria has no parent */
0056: public static final int NONE = 9;
0057:
0058: /** prefix to identify attributes referencing enclosing query */
0059: public static final String PARENT_QUERY_PREFIX = "parentQuery.";
0060:
0061: private Vector m_criteria;
0062: private int m_type;
0063: private boolean m_embraced;
0064: private boolean m_negative = false;
0065:
0066: // holding CriteriaFields for orderBy and groupBy
0067: private List orderby = null;
0068: private List groupby = null;
0069: private List prefetchedRelationships = null;
0070:
0071: // an optional alias to be used for this criteria
0072: private String m_alias = null;
0073:
0074: // PAW
0075: // an aliasPath to be used for this criteria
0076: private String m_aliasPath = null;
0077:
0078: // holds the path segment(s) to which the alias applies
0079: private UserAlias m_userAlias = null;
0080:
0081: /** the max. number of parameters in a IN-statement */
0082: protected static final int IN_LIMIT = getSqlInLimit();
0083:
0084: private QueryByCriteria m_query;
0085: private Criteria m_parentCriteria;
0086:
0087: // PAW
0088: // hint classes for paths of this criteria
0089: private Map m_pathClasses;
0090:
0091: /**
0092: * Constructor declaration
0093: */
0094: public Criteria() {
0095: m_criteria = new Vector();
0096: groupby = new ArrayList();
0097: orderby = new ArrayList();
0098: prefetchedRelationships = new ArrayList();
0099: m_type = NONE;
0100: m_embraced = false;
0101: // PAW
0102: m_pathClasses = new HashMap();
0103: }
0104:
0105: /**
0106: * Constructor with a SelectionCriteria
0107: * @param aSelectionCriteria SelectionCriteria
0108: */
0109: public Criteria(SelectionCriteria aSelectionCriteria) {
0110: this ();
0111: addSelectionCriteria(aSelectionCriteria);
0112: }
0113:
0114: /**
0115: * make a copy of the criteria
0116: * @param includeGroupBy if true
0117: * @param includeOrderBy if ture
0118: * @param includePrefetchedRelationships if true
0119: * @return a copy of the criteria
0120: */
0121: public Criteria copy(boolean includeGroupBy,
0122: boolean includeOrderBy,
0123: boolean includePrefetchedRelationships) {
0124: Criteria copy = new Criteria();
0125:
0126: copy.m_criteria = new Vector(this .m_criteria);
0127: copy.m_negative = this .m_negative;
0128:
0129: if (includeGroupBy) {
0130: copy.groupby = this .groupby;
0131: }
0132: if (includeOrderBy) {
0133: copy.orderby = this .orderby;
0134: }
0135: if (includePrefetchedRelationships) {
0136: copy.prefetchedRelationships = this .prefetchedRelationships;
0137: }
0138:
0139: return copy;
0140: }
0141:
0142: protected void addSelectionCriteria(SelectionCriteria selectionCrit) {
0143: selectionCrit.setCriteria(this );
0144: m_criteria.addElement(selectionCrit);
0145: }
0146:
0147: protected void addCriteria(Criteria crit) {
0148: crit.setParentCriteria(this );
0149: m_criteria.addElement(crit);
0150: }
0151:
0152: protected void addCriteria(Vector criteria) {
0153: Object crit;
0154:
0155: for (int i = 0; i < criteria.size(); i++) {
0156: crit = criteria.elementAt(i);
0157: if (crit instanceof SelectionCriteria) {
0158: addSelectionCriteria((SelectionCriteria) crit);
0159: } else if (crit instanceof Criteria) {
0160: addCriteria((Criteria) crit);
0161: }
0162: }
0163: }
0164:
0165: /**
0166: * Answer a List of InCriteria based on values, each InCriteria
0167: * contains only inLimit values
0168: * @param attribute
0169: * @param values
0170: * @param negative
0171: * @param inLimit the maximum number of values for IN (-1 for no limit)
0172: * @return List of InCriteria
0173: */
0174: protected List splitInCriteria(Object attribute, Collection values,
0175: boolean negative, int inLimit) {
0176: List result = new ArrayList();
0177: Collection inCollection = new ArrayList();
0178:
0179: if (values == null || values.isEmpty()) {
0180: // OQL creates empty Criteria for late binding
0181: result.add(buildInCriteria(attribute, negative, values));
0182: } else {
0183: Iterator iter = values.iterator();
0184:
0185: while (iter.hasNext()) {
0186: inCollection.add(iter.next());
0187: if (inCollection.size() == inLimit || !iter.hasNext()) {
0188: result.add(buildInCriteria(attribute, negative,
0189: inCollection));
0190: inCollection = new ArrayList();
0191: }
0192: }
0193: }
0194: return result;
0195: }
0196:
0197: private InCriteria buildInCriteria(Object attribute,
0198: boolean negative, Collection values) {
0199: if (negative) {
0200: // PAW
0201: // return ValueCriteria.buildNotInCriteria(attribute, values, getAlias());
0202: return ValueCriteria.buildNotInCriteria(attribute, values,
0203: getUserAlias(attribute));
0204: } else {
0205: // PAW
0206: // return ValueCriteria.buildInCriteria(attribute, values, getAlias());
0207: return ValueCriteria.buildInCriteria(attribute, values,
0208: getUserAlias(attribute));
0209: }
0210: }
0211:
0212: /**
0213: * Get an Enumeration with all sub criteria
0214: * @return Enumeration
0215: */
0216: public Enumeration getElements() {
0217: return getCriteria().elements();
0218: }
0219:
0220: /**
0221: * Get a Vector with all sub criteria
0222: * @return Vector
0223: */
0224: protected Vector getCriteria() {
0225: return m_criteria;
0226: }
0227:
0228: /**
0229: * Answer the type
0230: * @return int
0231: */
0232: public int getType() {
0233: return m_type;
0234: }
0235:
0236: /**
0237: * Set the type
0238: * @param type OR, AND, NONE
0239: */
0240: public void setType(int type) {
0241: m_type = type;
0242: }
0243:
0244: /**
0245: * ANDed criteria are embraced
0246: * @return true if embraced,
0247: */
0248: public boolean isEmbraced() {
0249: return m_embraced;
0250: }
0251:
0252: /**
0253: * Set embraced
0254: * @param embraced true if criteria is to be surrounded by braces
0255: */
0256: public void setEmbraced(boolean embraced) {
0257: m_embraced = embraced;
0258: }
0259:
0260: /**
0261: * Adds and equals (=) criteria,
0262: * customer_id = 10034
0263: *
0264: * @param attribute The field name to be used
0265: * @param value An object representing the value of the field
0266: */
0267: public void addEqualTo(String attribute, Object value) {
0268: // PAW
0269: // addSelectionCriteria(ValueCriteria.buildEqualToCriteria(attribute, value, getAlias()));
0270: addSelectionCriteria(ValueCriteria.buildEqualToCriteria(
0271: attribute, value, getUserAlias(attribute)));
0272: }
0273:
0274: /**
0275: * Adds and equals (=) criteria,
0276: * CUST_ID = 10034
0277: * attribute will NOT be translated into column name
0278: *
0279: * @param column The column name to be used without translation
0280: * @param value An object representing the value of the column
0281: */
0282: public void addColumnEqualTo(String column, Object value) {
0283: // PAW
0284: // SelectionCriteria c = ValueCriteria.buildEqualToCriteria(column, value, getAlias());
0285: SelectionCriteria c = ValueCriteria.buildEqualToCriteria(
0286: column, value, getUserAlias(column));
0287: c.setTranslateAttribute(false);
0288: addSelectionCriteria(c);
0289: }
0290:
0291: /**
0292: * Adds and equals (=) criteria for field comparison.
0293: * The field name will be translated into the appropriate columnName by SqlStatement.
0294: * The attribute will NOT be translated into column name
0295: *
0296: * @param column The column name to be used without translation
0297: * @param fieldName An object representing the value of the field
0298: */
0299: public void addColumnEqualToField(String column, Object fieldName) {
0300: // PAW
0301: //SelectionCriteria c = FieldCriteria.buildEqualToCriteria(column, fieldName, getAlias());
0302: SelectionCriteria c = FieldCriteria.buildEqualToCriteria(
0303: column, fieldName, getUserAlias(column));
0304: c.setTranslateAttribute(false);
0305: addSelectionCriteria(c);
0306: }
0307:
0308: /**
0309: * Adds and equals (=) criteria for field comparison.
0310: * The field name will be translated into the appropriate columnName by SqlStatement.
0311: * <br>
0312: * name = boss.name
0313: *
0314: * @param attribute The field name to be used
0315: * @param fieldName The field name to compare with
0316: */
0317: public void addEqualToField(String attribute, String fieldName) {
0318: // PAW
0319: // FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, fieldName, getAlias());
0320: FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute,
0321: fieldName, getUserAlias(attribute));
0322: addSelectionCriteria(c);
0323: }
0324:
0325: /**
0326: * Adds and equals (=) criteria for field comparison.
0327: * The field name will be translated into the appropriate columnName by SqlStatement.
0328: * <br>
0329: * name <> boss.name
0330: *
0331: * @param attribute The field name to be used
0332: * @param fieldName The field name to compare with
0333: */
0334: public void addNotEqualToField(String attribute, String fieldName) {
0335: // PAW
0336: // SelectionCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, fieldName, getAlias());
0337: SelectionCriteria c = FieldCriteria.buildNotEqualToCriteria(
0338: attribute, fieldName, getUserAlias(attribute));
0339: addSelectionCriteria(c);
0340: }
0341:
0342: /**
0343: * Adds and equals (<>) criteria for column comparison.
0344: * The column Name will NOT be translated.
0345: * <br>
0346: * name <> T_BOSS.LASTNMAE
0347: *
0348: * @param attribute The field name to be used
0349: * @param colName The name of the column to compare with
0350: */
0351: public void addNotEqualToColumn(String attribute, String colName) {
0352: // PAW
0353: // FieldCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, colName, getAlias());
0354: FieldCriteria c = FieldCriteria.buildNotEqualToCriteria(
0355: attribute, colName, getUserAlias(attribute));
0356: c.setTranslateField(false);
0357: addSelectionCriteria(c);
0358: }
0359:
0360: /**
0361: * Adds and equals (=) criteria for column comparison.
0362: * The column Name will NOT be translated.
0363: * <br>
0364: * name = T_BOSS.LASTNMAE
0365: *
0366: * @param attribute The field name to be used
0367: * @param colName The name of the column to compare with
0368: */
0369: public void addEqualToColumn(String attribute, String colName) {
0370: // FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, colName, getAlias());
0371: FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute,
0372: colName, getUserAlias(attribute));
0373: c.setTranslateField(false);
0374: addSelectionCriteria(c);
0375: }
0376:
0377: /**
0378: * Adds GreaterOrEqual Than (>=) criteria,
0379: * customer_id >= 10034
0380: *
0381: * @param attribute The field name to be used
0382: * @param value An object representing the value of the field
0383: */
0384: public void addGreaterOrEqualThan(Object attribute, Object value) {
0385: // PAW
0386: // addSelectionCriteria(ValueCriteria.buildNotLessCriteria(attribute, value, getAlias()));
0387: addSelectionCriteria(ValueCriteria.buildNotLessCriteria(
0388: attribute, value, getUserAlias(attribute)));
0389: }
0390:
0391: /**
0392: * Adds GreaterOrEqual Than (>=) criteria,
0393: * customer_id >= person_id
0394: *
0395: * @param attribute The field name to be used
0396: * @param value The field name to compare with
0397: */
0398: public void addGreaterOrEqualThanField(String attribute,
0399: Object value) {
0400: // PAW
0401: // addSelectionCriteria(FieldCriteria.buildNotLessCriteria(attribute, value, getAlias()));
0402: addSelectionCriteria(FieldCriteria.buildNotLessCriteria(
0403: attribute, value, getUserAlias(attribute)));
0404: }
0405:
0406: /**
0407: * Adds LessOrEqual Than (<=) criteria,
0408: * customer_id <= 10034
0409: *
0410: * @param attribute The field name to be used
0411: * @param value An object representing the value of the field
0412: */
0413: public void addLessOrEqualThan(Object attribute, Object value) {
0414: // PAW
0415: // addSelectionCriteria(ValueCriteria.buildNotGreaterCriteria(attribute, value, getAlias()));
0416: addSelectionCriteria(ValueCriteria.buildNotGreaterCriteria(
0417: attribute, value, getUserAlias(attribute)));
0418: }
0419:
0420: /**
0421: * Adds LessOrEqual Than (<=) criteria,
0422: * customer_id <= person_id
0423: *
0424: * @param attribute The field name to be used
0425: * @param value The field name to compare with
0426: */
0427: public void addLessOrEqualThanField(String attribute, Object value) {
0428: // PAW
0429: // addSelectionCriteria(FieldCriteria.buildNotGreaterCriteria(attribute, value, getAlias()));
0430: addSelectionCriteria(FieldCriteria.buildNotGreaterCriteria(
0431: attribute, value, getUserAlias(attribute)));
0432: }
0433:
0434: /**
0435: * Adds Like (LIKE) criteria,
0436: * customer_name LIKE "m%ller"
0437: *
0438: * @see LikeCriteria
0439: * @param attribute The field name to be used
0440: * @param value An object representing the value of the field
0441: */
0442: public void addLike(Object attribute, Object value) {
0443: // PAW
0444: // addSelectionCriteria(ValueCriteria.buildLikeCriteria(attribute, value, getAlias()));
0445: addSelectionCriteria(ValueCriteria.buildLikeCriteria(attribute,
0446: value, getUserAlias(attribute)));
0447: }
0448:
0449: /**
0450: * Adds Like (NOT LIKE) criteria,
0451: * customer_id NOT LIKE 10034
0452: *
0453: * @see LikeCriteria
0454: * @param attribute The field name to be used
0455: * @param value An object representing the value of the field
0456: */
0457: public void addNotLike(String attribute, Object value) {
0458: // PAW
0459: // addSelectionCriteria(ValueCriteria.buildNotLikeCriteria(attribute, value, getAlias()));
0460: addSelectionCriteria(ValueCriteria.buildNotLikeCriteria(
0461: attribute, value, getUserAlias(attribute)));
0462: }
0463:
0464: /**
0465: * Adds NotEqualTo (<>) criteria,
0466: * customer_id <> 10034
0467: *
0468: * @param attribute The field name to be used
0469: * @param value An object representing the value of the field
0470: */
0471: public void addNotEqualTo(Object attribute, Object value) {
0472: // PAW
0473: // addSelectionCriteria(ValueCriteria.buildNotEqualToCriteria(attribute, value, getAlias()));
0474: addSelectionCriteria(ValueCriteria.buildNotEqualToCriteria(
0475: attribute, value, getUserAlias(attribute)));
0476: }
0477:
0478: /**
0479: * Adds Greater Than (>) criteria,
0480: * customer_id > 10034
0481: *
0482: * @param attribute The field name to be used
0483: * @param value An object representing the value of the field
0484: */
0485: public void addGreaterThan(Object attribute, Object value) {
0486: // PAW
0487: // addSelectionCriteria(ValueCriteria.buildGreaterCriteria(attribute, value, getAlias()));
0488: addSelectionCriteria(ValueCriteria.buildGreaterCriteria(
0489: attribute, value, getUserAlias(attribute)));
0490: }
0491:
0492: /**
0493: * Adds Greater Than (>) criteria,
0494: * customer_id > person_id
0495: *
0496: * @param attribute The field name to be used
0497: * @param value The field to compare with
0498: */
0499: public void addGreaterThanField(String attribute, Object value) {
0500: // PAW
0501: // addSelectionCriteria(FieldCriteria.buildGreaterCriteria(attribute, value, getAlias()));
0502: addSelectionCriteria(FieldCriteria.buildGreaterCriteria(
0503: attribute, value, getUserAlias(attribute)));
0504: }
0505:
0506: /**
0507: * Adds Less Than (<) criteria,
0508: * customer_id < 10034
0509: *
0510: * @param attribute The field name to be used
0511: * @param value An object representing the value of the field
0512: */
0513: public void addLessThan(Object attribute, Object value) {
0514: // PAW
0515: // addSelectionCriteria(ValueCriteria.buildLessCriteria(attribute, value, getAlias()));
0516: addSelectionCriteria(ValueCriteria.buildLessCriteria(attribute,
0517: value, getUserAlias(attribute)));
0518: }
0519:
0520: /**
0521: * Adds Less Than (<) criteria,
0522: * customer_id < person_id
0523: *
0524: * @param attribute The field name to be used
0525: * @param value The field to compare with
0526: */
0527: public void addLessThanField(String attribute, Object value) {
0528: // PAW
0529: // addSelectionCriteria(FieldCriteria.buildLessCriteria(attribute, value, getAlias()));
0530: addSelectionCriteria(FieldCriteria.buildLessCriteria(attribute,
0531: value, getUserAlias(attribute)));
0532: }
0533:
0534: /**
0535: * Adds a field for orderBy, order is ASCENDING
0536: * @param fieldName The field name to be used
0537: * @deprecated use #addOrderByAscending(String fieldName)
0538: */
0539: public void addOrderBy(String fieldName) {
0540: addOrderBy(fieldName, true);
0541: }
0542:
0543: /**
0544: * Adds a field for orderBy
0545: * @param fieldName the field name to be used
0546: * @param sortAscending true for ASCENDING, false for DESCENDING
0547: * @deprecated use QueryByCriteria#addOrderBy
0548: */
0549: public void addOrderBy(String fieldName, boolean sortAscending) {
0550: if (fieldName != null) {
0551: _getOrderby()
0552: .add(new FieldHelper(fieldName, sortAscending));
0553: }
0554: }
0555:
0556: /**
0557: * Adds a field for orderBy
0558: * @param aField the Field
0559: * @deprecated use QueryByCriteria#addOrderBy
0560: */
0561: public void addOrderBy(FieldHelper aField) {
0562: if (aField != null) {
0563: _getOrderby().add(aField);
0564: }
0565: }
0566:
0567: /**
0568: * Adds a field for orderBy ASCENDING
0569: * @param fieldName The field name to be used
0570: * @deprecated use QueryByCriteria#addOrderByAscending
0571: */
0572: public void addOrderByAscending(String fieldName) {
0573: addOrderBy(fieldName, true);
0574: }
0575:
0576: /**
0577: * Adds a field for orderBy DESCENDING
0578: * @param fieldName The field name to be used
0579: * @deprecated use QueryByCriteria#addOrderByDescending
0580: */
0581: public void addOrderByDescending(String fieldName) {
0582: addOrderBy(fieldName, false);
0583: }
0584:
0585: /**
0586: * Answer the orderBy of all Criteria and Sub Criteria
0587: * the elements are of class Criteria.FieldHelper
0588: * @return List
0589: */
0590: List getOrderby() {
0591: List result = _getOrderby();
0592: Iterator iter = getCriteria().iterator();
0593: Object crit;
0594:
0595: while (iter.hasNext()) {
0596: crit = iter.next();
0597: if (crit instanceof Criteria) {
0598: result.addAll(((Criteria) crit).getOrderby());
0599: }
0600: }
0601:
0602: return result;
0603: }
0604:
0605: /**
0606: * Answer the Vector with all orderBy,
0607: * the elements are of class Criteria.FieldHelper
0608: * @return List
0609: */
0610: protected List _getOrderby() {
0611: return orderby;
0612: }
0613:
0614: /**
0615: * ORs two sets of criteria together:
0616: * <pre>
0617: * active = true AND balance < 0 OR active = true AND overdraft = 0
0618: * </pre>
0619: * @param pc criteria
0620: */
0621: public void addOrCriteria(Criteria pc) {
0622: if (!m_criteria.isEmpty()) {
0623: pc.setEmbraced(true);
0624: pc.setType(OR);
0625: addCriteria(pc);
0626: } else {
0627: setEmbraced(false);
0628: pc.setType(OR);
0629: addCriteria(pc);
0630: }
0631: }
0632:
0633: /**
0634: * Adds is Null criteria,
0635: * customer_id is Null
0636: *
0637: * @param attribute The field name to be used
0638: */
0639: public void addIsNull(String attribute) {
0640: // PAW
0641: //addSelectionCriteria(ValueCriteria.buildNullCriteria(attribute, getAlias()));
0642: addSelectionCriteria(ValueCriteria.buildNullCriteria(attribute,
0643: getUserAlias(attribute)));
0644: }
0645:
0646: /**
0647: * Adds is Null criteria,
0648: * customer_id is Null
0649: * The attribute will NOT be translated into column name
0650: *
0651: * @param column The column name to be used without translation
0652: */
0653: public void addColumnIsNull(String column) {
0654: // PAW
0655: //SelectionCriteria c = ValueCriteria.buildNullCriteria(column, getAlias());
0656: SelectionCriteria c = ValueCriteria.buildNullCriteria(column,
0657: getUserAlias(column));
0658: c.setTranslateAttribute(false);
0659: addSelectionCriteria(c);
0660: }
0661:
0662: /**
0663: * Adds not Null criteria,
0664: * customer_id is not Null
0665: *
0666: * @param attribute The field name to be used
0667: */
0668: public void addNotNull(String attribute) {
0669: // PAW
0670: //addSelectionCriteria(ValueCriteria.buildNotNullCriteria(attribute, getAlias()));
0671: addSelectionCriteria(ValueCriteria.buildNotNullCriteria(
0672: attribute, getUserAlias(attribute)));
0673: }
0674:
0675: /**
0676: * Adds not Null criteria,
0677: * customer_id is not Null
0678: * The attribute will NOT be translated into column name
0679: *
0680: * @param column The column name to be used without translation
0681: */
0682: public void addColumnNotNull(String column) {
0683: // PAW
0684: // SelectionCriteria c = ValueCriteria.buildNotNullCriteria(column, getAlias());
0685: SelectionCriteria c = ValueCriteria.buildNotNullCriteria(
0686: column, getUserAlias(column));
0687: c.setTranslateAttribute(false);
0688: addSelectionCriteria(c);
0689: }
0690:
0691: /**
0692: * Adds BETWEEN criteria,
0693: * customer_id between 1 and 10
0694: *
0695: * @param attribute The field name to be used
0696: * @param value1 The lower boundary
0697: * @param value2 The upper boundary
0698: */
0699: public void addBetween(Object attribute, Object value1,
0700: Object value2) {
0701: // PAW
0702: // addSelectionCriteria(ValueCriteria.buildBeweenCriteria(attribute, value1, value2, getAlias()));
0703: addSelectionCriteria(ValueCriteria.buildBeweenCriteria(
0704: attribute, value1, value2, getUserAlias(attribute)));
0705: }
0706:
0707: /**
0708: * Adds NOT BETWEEN criteria,
0709: * customer_id not between 1 and 10
0710: *
0711: * @param attribute The field name to be used
0712: * @param value1 The lower boundary
0713: * @param value2 The upper boundary
0714: */
0715: public void addNotBetween(Object attribute, Object value1,
0716: Object value2) {
0717: // PAW
0718: // addSelectionCriteria(ValueCriteria.buildNotBeweenCriteria(attribute, value1, value2, getAlias()));
0719: addSelectionCriteria(ValueCriteria.buildNotBeweenCriteria(
0720: attribute, value1, value2, getUserAlias(attribute)));
0721: }
0722:
0723: /**
0724: * Adds IN criteria,
0725: * customer_id in(1,10,33,44)
0726: * large values are split into multiple InCriteria
0727: * IN (1,10) OR IN(33, 44)
0728: *
0729: * @param attribute The field name to be used
0730: * @param values The value Collection
0731: */
0732: public void addIn(String attribute, Collection values) {
0733: List list = splitInCriteria(attribute, values, false, IN_LIMIT);
0734: int index = 0;
0735: InCriteria inCrit;
0736: Criteria allInCritaria;
0737:
0738: inCrit = (InCriteria) list.get(index);
0739: allInCritaria = new Criteria(inCrit);
0740:
0741: for (index = 1; index < list.size(); index++) {
0742: inCrit = (InCriteria) list.get(index);
0743: allInCritaria.addOrCriteria(new Criteria(inCrit));
0744: }
0745:
0746: addAndCriteria(allInCritaria);
0747: }
0748:
0749: /**
0750: * Adds IN criteria,
0751: * customer_id in(1,10,33,44)
0752: * large values are split into multiple InCriteria
0753: * IN (1,10) OR IN(33, 44) </br>
0754: * The attribute will NOT be translated into column name
0755: *
0756: * @param column The column name to be used without translation
0757: * @param values The value Collection
0758: */
0759: public void addColumnIn(String column, Collection values) {
0760: List list = splitInCriteria(column, values, false, IN_LIMIT);
0761: int index = 0;
0762: InCriteria inCrit;
0763: Criteria allInCritaria;
0764:
0765: inCrit = (InCriteria) list.get(index);
0766: inCrit.setTranslateAttribute(false);
0767: allInCritaria = new Criteria(inCrit);
0768:
0769: for (index = 1; index < list.size(); index++) {
0770: inCrit = (InCriteria) list.get(index);
0771: inCrit.setTranslateAttribute(false);
0772: allInCritaria.addOrCriteria(new Criteria(inCrit));
0773: }
0774:
0775: addAndCriteria(allInCritaria);
0776: }
0777:
0778: /**
0779: * Adds NOT IN criteria,
0780: * customer_id not in(1,10,33,44)
0781: * large values are split into multiple InCriteria
0782: * NOT IN (1,10) AND NOT IN(33, 44)
0783: *
0784: * @param attribute The field name to be used
0785: * @param values The value Collection
0786: */
0787: public void addNotIn(String attribute, Collection values) {
0788: List list = splitInCriteria(attribute, values, true, IN_LIMIT);
0789: InCriteria inCrit;
0790: for (int index = 0; index < list.size(); index++) {
0791: inCrit = (InCriteria) list.get(index);
0792: addSelectionCriteria(inCrit);
0793: }
0794: }
0795:
0796: /**
0797: * IN Criteria with SubQuery
0798: * @param attribute The field name to be used
0799: * @param subQuery The subQuery
0800: */
0801: public void addIn(Object attribute, Query subQuery) {
0802: // PAW
0803: // addSelectionCriteria(ValueCriteria.buildInCriteria(attribute, subQuery, getAlias()));
0804: addSelectionCriteria(ValueCriteria.buildInCriteria(attribute,
0805: subQuery, getUserAlias(attribute)));
0806: }
0807:
0808: /**
0809: * NOT IN Criteria with SubQuery
0810: * @param attribute The field name to be used
0811: * @param subQuery The subQuery
0812: */
0813: public void addNotIn(String attribute, Query subQuery) {
0814: // PAW
0815: // addSelectionCriteria(ValueCriteria.buildNotInCriteria(attribute, subQuery, getAlias()));
0816: addSelectionCriteria(ValueCriteria.buildNotInCriteria(
0817: attribute, subQuery, getUserAlias(attribute)));
0818: }
0819:
0820: /**
0821: * Adds freeform SQL criteria,
0822: * REVERSE(name) like 're%'
0823: *
0824: * @param anSqlStatment The free form SQL-Statement
0825: */
0826: public void addSql(String anSqlStatment) {
0827: addSelectionCriteria(new SqlCriteria(anSqlStatment));
0828: }
0829:
0830: /**
0831: * ANDs two sets of criteria together:
0832: *
0833: * @param pc criteria
0834: */
0835: public void addAndCriteria(Criteria pc) {
0836: // by combining a second criteria by 'AND' the existing criteria needs to be enclosed
0837: // in parenthesis
0838: if (!m_criteria.isEmpty()) {
0839: this .setEmbraced(true);
0840: pc.setEmbraced(true);
0841: pc.setType(AND);
0842: addCriteria(pc);
0843: } else {
0844: setEmbraced(false);
0845: pc.setType(AND);
0846: addCriteria(pc);
0847: }
0848: }
0849:
0850: /**
0851: * Adds an exists(sub query)
0852: *
0853: * @param subQuery sub-query
0854: */
0855: public void addExists(Query subQuery) {
0856: addSelectionCriteria(new ExistsCriteria(subQuery, false));
0857: }
0858:
0859: /**
0860: * Adds a not exists(sub query)
0861: *
0862: * @param subQuery sub-query
0863: */
0864: public void addNotExists(Query subQuery) {
0865: addSelectionCriteria(new ExistsCriteria(subQuery, true));
0866: }
0867:
0868: /**
0869: * Answer true if no sub criteria available
0870: * @return boolean
0871: */
0872: public boolean isEmpty() {
0873: return m_criteria.isEmpty();
0874: }
0875:
0876: /**
0877: * Gets the groupby for ReportQueries of all Criteria and Sub Criteria
0878: * the elements are of class FieldHelper
0879: * @return List of FieldHelper
0880: */
0881: List getGroupby() {
0882: List result = _getGroupby();
0883: Iterator iter = getCriteria().iterator();
0884: Object crit;
0885:
0886: while (iter.hasNext()) {
0887: crit = iter.next();
0888: if (crit instanceof Criteria) {
0889: result.addAll(((Criteria) crit).getGroupby());
0890: }
0891: }
0892:
0893: return result;
0894: }
0895:
0896: /**
0897: * Gets the groupby for ReportQueries,
0898: * the elements are of class Criteria.FieldHelper
0899: * @return List of Criteria.FieldHelper
0900: */
0901: protected List _getGroupby() {
0902: return groupby;
0903: }
0904:
0905: /**
0906: * Adds a groupby fieldName for ReportQueries.
0907: * @param fieldName The groupby to set
0908: * @deprecated use QueryByCriteria#addGroupBy
0909: */
0910: public void addGroupBy(String fieldName) {
0911: if (fieldName != null) {
0912: _getGroupby().add(new FieldHelper(fieldName, false));
0913: }
0914: }
0915:
0916: /**
0917: * Adds a field for groupby
0918: * @param aField the Field
0919: * @deprecated use QueryByCriteria#addGroupBy
0920: */
0921: public void addGroupBy(FieldHelper aField) {
0922: if (aField != null) {
0923: _getGroupby().add(aField);
0924: }
0925: }
0926:
0927: /**
0928: * Adds an array of groupby fieldNames for ReportQueries.
0929: * @param fieldNames The groupby to set
0930: * @deprecated use QueryByCriteria#addGroupBy
0931: */
0932: public void addGroupBy(String[] fieldNames) {
0933: for (int i = 0; i < fieldNames.length; i++) {
0934: addGroupBy(fieldNames[i]);
0935: }
0936: }
0937:
0938: /**
0939: * Returns the prefetchedRelationships.
0940: * @return List
0941: */
0942: List getPrefetchedRelationships() {
0943: return prefetchedRelationships;
0944: }
0945:
0946: /**
0947: * add the name of a Relationship for prefetch read
0948: * @param aName the name of the relationship
0949: * @deprecated use QueryByCriteria#addPrefetchedRelationship
0950: */
0951: public void addPrefetchedRelationship(String aName) {
0952: getPrefetchedRelationships().add(aName);
0953: }
0954:
0955: /**
0956: * read the prefetchInLimit from Config based on OJB.properties
0957: */
0958: private static int getSqlInLimit() {
0959: try {
0960: PersistenceBrokerConfiguration config = (PersistenceBrokerConfiguration) PersistenceBrokerFactory
0961: .getConfigurator().getConfigurationFor(null);
0962: return config.getSqlInLimit();
0963: } catch (ConfigurationException e) {
0964: return 200;
0965: }
0966: }
0967:
0968: /**
0969: * @return String
0970: */
0971: public String getAlias() {
0972: return m_alias;
0973: }
0974:
0975: /**
0976: * @return String
0977: */
0978: // PAW
0979: public UserAlias getUserAlias() {
0980: return m_userAlias;
0981: }
0982:
0983: // PAW
0984: /**
0985: * Retrieves or if necessary, creates a user alias to be used
0986: * by a child criteria
0987: * @param attribute The alias to set
0988: */
0989: private UserAlias getUserAlias(Object attribute) {
0990: if (m_userAlias != null) {
0991: return m_userAlias;
0992: }
0993: if (!(attribute instanceof String)) {
0994: return null;
0995: }
0996: if (m_alias == null) {
0997: return null;
0998: }
0999: if (m_aliasPath == null) {
1000: boolean allPathsAliased = true;
1001: return new UserAlias(m_alias, (String) attribute,
1002: allPathsAliased);
1003: }
1004: return new UserAlias(m_alias, (String) attribute, m_aliasPath);
1005: }
1006:
1007: /**
1008: * Sets the alias. Empty String is regarded as null.
1009: * @param alias The alias to set
1010: */
1011: public void setAlias(String alias) {
1012: if (alias == null || alias.trim().equals("")) {
1013: m_alias = null;
1014: } else {
1015: m_alias = alias;
1016: }
1017:
1018: // propagate to SelectionCriteria,not to Criteria
1019: for (int i = 0; i < m_criteria.size(); i++) {
1020: if (!(m_criteria.elementAt(i) instanceof Criteria)) {
1021: ((SelectionCriteria) m_criteria.elementAt(i))
1022: .setAlias(m_alias);
1023: }
1024: }
1025: }
1026:
1027: // PAW
1028: /**
1029: * Sets the alias. Empty String is regarded as null.
1030: * @param alias The alias to set
1031: * @param aliasPath The path segment(s) to which the alias applies
1032: */
1033: public void setAlias(String alias, String aliasPath) {
1034: if (alias == null || alias.trim().equals("")) {
1035: m_alias = null;
1036: } else {
1037: m_alias = alias;
1038: m_aliasPath = aliasPath;
1039: }
1040:
1041: // propagate to SelectionCriteria,not to Criteria
1042: for (int i = 0; i < m_criteria.size(); i++) {
1043: if (!(m_criteria.elementAt(i) instanceof Criteria)) {
1044: ((SelectionCriteria) m_criteria.elementAt(i)).setAlias(
1045: m_alias, aliasPath);
1046: }
1047: }
1048: }
1049:
1050: // PAW
1051: /**
1052: * Sets the alias using a userAlias object.
1053: * @param userAlias The alias to set
1054: */
1055: public void setAlias(UserAlias userAlias) {
1056: m_alias = userAlias.getName();
1057:
1058: // propagate to SelectionCriteria,not to Criteria
1059: for (int i = 0; i < m_criteria.size(); i++) {
1060: if (!(m_criteria.elementAt(i) instanceof Criteria)) {
1061: ((SelectionCriteria) m_criteria.elementAt(i))
1062: .setAlias(userAlias);
1063: }
1064: }
1065: }
1066:
1067: /**
1068: * @return the query containing the criteria
1069: */
1070: public QueryByCriteria getQuery() {
1071: if (getParentCriteria() != null) {
1072: return getParentCriteria().getQuery();
1073: } else {
1074: return m_query;
1075: }
1076:
1077: }
1078:
1079: /**
1080: * @param query
1081: */
1082: void setQuery(QueryByCriteria query) {
1083: m_query = query;
1084: }
1085:
1086: /**
1087: * @return the parent criteria
1088: */
1089: public Criteria getParentCriteria() {
1090: return m_parentCriteria;
1091: }
1092:
1093: /**
1094: * @param criteria
1095: */
1096: void setParentCriteria(Criteria criteria) {
1097: m_parentCriteria = criteria;
1098: }
1099:
1100: /**
1101: * @see Object#toString()
1102: */
1103: public String toString() {
1104: if (isNegative()) {
1105: return "-" + m_criteria.toString();
1106: } else {
1107: return m_criteria.toString();
1108: }
1109: }
1110:
1111: /**
1112: * @return Returns the negative.
1113: */
1114: public boolean isNegative() {
1115: return m_negative;
1116: }
1117:
1118: /**
1119: * Flags the whole Criteria as negative.
1120: * @param negative The negative to set.
1121: */
1122: public void setNegative(boolean negative) {
1123: m_negative = negative;
1124: }
1125:
1126: // PAW
1127: /**
1128: * Add a hint Class for a path. Used for relationships to extents.<br>
1129: * SqlStatment will use these hint classes when resolving the path.
1130: * Without these hints SqlStatment will use the base class the
1131: * relationship points to ie: Article instead of CdArticle.
1132: *
1133: * @param aPath the path segment ie: allArticlesInGroup
1134: * @param aClass the Class ie: CdArticle
1135: * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1136: */
1137: public void addPathClass(String aPath, Class aClass) {
1138: List pathClasses = (List) m_pathClasses.get(aPath);
1139: if (pathClasses == null) {
1140: setPathClass(aPath, aClass);
1141: } else {
1142: pathClasses.add(aClass);
1143: //m_pathClasses.put(aPath, pathClasses);
1144: }
1145: }
1146:
1147: /**
1148: * Set the Class for a path. Used for relationships to extents.<br>
1149: * SqlStatment will use this class when resolving the path.
1150: * Without this hint SqlStatment will use the base class the
1151: * relationship points to ie: Article instead of CdArticle.
1152: * Using this method is the same as adding just one hint
1153: *
1154: * @param aPath the path segment ie: allArticlesInGroup
1155: * @param aClass the Class ie: CdArticle
1156: * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1157: * @see #addPathClass
1158: */
1159: public void setPathClass(String aPath, Class aClass) {
1160: List pathClasses = new ArrayList(1);
1161: pathClasses.add(aClass);
1162: m_pathClasses.put(aPath, pathClasses);
1163: }
1164:
1165: /**
1166: * Get the a List of Class objects used as hints for a path
1167: *
1168: * @param aPath the path segment ie: allArticlesInGroup
1169: * @return a List o Class objects to be used in SqlStatment
1170: * @see #addPathClass
1171: * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1172: */
1173: public List getClassesForPath(String aPath) {
1174: return (List) getPathClasses().get(aPath);
1175: }
1176:
1177: /**
1178: * Gets the pathClasses.
1179: * A Map containing hints about what Class to be used for what path segment
1180: * If local instance not set, try parent Criteria's instance. If this is
1181: * the top-level Criteria, try the m_query's instance
1182: * @return Returns a Map
1183: */
1184: public Map getPathClasses() {
1185: if (m_pathClasses.isEmpty()) {
1186: if (m_parentCriteria == null) {
1187: if (m_query == null) {
1188: return m_pathClasses;
1189: } else {
1190: return m_query.getPathClasses();
1191: }
1192: } else {
1193: return m_parentCriteria.getPathClasses();
1194: }
1195: } else {
1196: return m_pathClasses;
1197: }
1198: }
1199:
1200: }
|