001: package org.apache.ojb.broker.query;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import java.util.Collection;
019: import java.util.HashSet;
020: import java.util.Vector;
021:
022: import org.apache.ojb.broker.metadata.ClassDescriptor;
023: import org.apache.ojb.broker.metadata.DescriptorRepository;
024: import org.apache.ojb.broker.metadata.FieldDescriptor;
025: import org.apache.ojb.broker.metadata.MetadataManager;
026:
027: /**
028: * Insert the type's description here.
029: * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
030: * @version $Id: QueryFactory.java,v 1.17.2.1 2005/12/21 22:27:09 tomdz Exp $
031: */
032: public final class QueryFactory {
033: private static DescriptorRepository getRepository() {
034: return MetadataManager.getInstance().getRepository();
035: }
036:
037: /**
038: * create a new ReportQueryByCriteria
039: * @param classToSearchFrom
040: * @param criteria
041: * @param distinct
042: * @return ReportQueryByCriteria
043: */
044: public static ReportQueryByCriteria newReportQuery(
045: Class classToSearchFrom, String[] columns,
046: Criteria criteria, boolean distinct) {
047: criteria = addCriteriaForOjbConcreteClasses(getRepository()
048: .getDescriptorFor(classToSearchFrom), criteria);
049: return new ReportQueryByCriteria(classToSearchFrom, columns,
050: criteria, distinct);
051: }
052:
053: /**
054: * create a new ReportQueryByCriteria
055: * @param classToSearchFrom
056: * @param criteria
057: * @param distinct
058: * @return ReportQueryByCriteria
059: */
060: public static ReportQueryByCriteria newReportQuery(
061: Class classToSearchFrom, Criteria criteria, boolean distinct) {
062: criteria = addCriteriaForOjbConcreteClasses(getRepository()
063: .getDescriptorFor(classToSearchFrom), criteria);
064: return newReportQuery(classToSearchFrom, null, criteria,
065: distinct);
066: }
067:
068: /**
069: * create a new ReportQueryByCriteria
070: * @param classToSearchFrom
071: * @param criteria
072: * @return ReportQueryByCriteria
073: */
074: public static ReportQueryByCriteria newReportQuery(
075: Class classToSearchFrom, Criteria criteria) {
076: return newReportQuery(classToSearchFrom, criteria, false);
077: }
078:
079: /**
080: * Method declaration
081: * @param classToSearchFrom
082: * @param criteria
083: * @param distinct
084: * @return QueryByCriteria
085: */
086: public static QueryByCriteria newQuery(Class classToSearchFrom,
087: Criteria criteria, boolean distinct) {
088: criteria = addCriteriaForOjbConcreteClasses(getRepository()
089: .getDescriptorFor(classToSearchFrom), criteria);
090: return new QueryByCriteria(classToSearchFrom, criteria,
091: distinct);
092: }
093:
094: /**
095: * Method declaration
096: * @param classToSearchFrom
097: * @param criteria
098: * @return QueryByCriteria
099: */
100: public static QueryByCriteria newQuery(Class classToSearchFrom,
101: Criteria criteria) {
102: return newQuery(classToSearchFrom, criteria, false);
103: }
104:
105: /**
106: * Return a QueryByIdentity for example_or_identity
107: * @param example_or_identity
108: * @return QueryByIdentity
109: */
110: public static QueryByIdentity newQuery(Object example_or_identity) {
111: return newQueryByIdentity(example_or_identity);
112: }
113:
114: /**
115: * Return a QueryByIdentity for example_or_identity
116: * @param example_or_identity
117: * @return QueryByIdentity
118: */
119: public static QueryByIdentity newQueryByIdentity(
120: Object example_or_identity) {
121: return new QueryByIdentity(example_or_identity);
122: }
123:
124: /**
125: * Return a QueryByCriteria for example
126: * <br>Use with care because building of Query is not foolproof !!!
127: * @param example
128: * @return QueryByCriteria
129: */
130: public static QueryByCriteria newQueryByExample(Object example) {
131: return new QueryByCriteria(example);
132: }
133:
134: /**
135: * @param classToSearchFrom
136: * @param indirectionTable
137: * @param criteria
138: * @param distinct
139: * @return QueryByMtoNCriteria
140: */
141: public static QueryByMtoNCriteria newQuery(Class classToSearchFrom,
142: String indirectionTable, Criteria criteria, boolean distinct) {
143: criteria = addCriteriaForOjbConcreteClasses(getRepository()
144: .getDescriptorFor(classToSearchFrom), criteria);
145: return new QueryByMtoNCriteria(classToSearchFrom,
146: indirectionTable, criteria, distinct);
147: }
148:
149: /**
150: * @param classToSearchFrom
151: * @param indirectionTable
152: * @param criteria
153: * @return QueryByCriteria
154: */
155: public static QueryByCriteria newQuery(Class classToSearchFrom,
156: String indirectionTable, Criteria criteria) {
157: criteria = addCriteriaForOjbConcreteClasses(getRepository()
158: .getDescriptorFor(classToSearchFrom), criteria);
159: return new QueryByMtoNCriteria(classToSearchFrom,
160: indirectionTable, criteria);
161: }
162:
163: /**
164: * Factory method for QueryBySQL
165: * @param classToSearchFrom
166: * @param anSqlStatement
167: * @return QueryBySQL
168: */
169: public static QueryBySQL newQuery(Class classToSearchFrom,
170: String anSqlStatement) {
171: return new QueryBySQL(classToSearchFrom, anSqlStatement);
172: }
173:
174: /**
175: * Searches the class descriptor for the ojbConcrete class attribute
176: * if it finds the concrete class attribute, append a where clause which
177: * specifies we can load all classes that are this type or extents of this type.
178: * @param cld
179: * @return the extent classes
180: */
181: private static Collection getExtentClasses(ClassDescriptor cld) {
182: /**
183: * 1. check if this class has a ojbConcreteClass attribute
184: */
185: FieldDescriptor fd = cld
186: .getFieldDescriptorByName(ClassDescriptor.OJB_CONCRETE_CLASS);
187: Collection classes = new HashSet(); // use same class only once
188: if (fd != null) {
189: classes.add(cld.getClassOfObject().getName());
190: }
191:
192: /**
193: * 2. if this class has extents/is an extent search for all extents
194: */
195: if (cld.isExtent()) {
196: Vector extentClasses = cld.getExtentClasses();
197:
198: /**
199: * 3. get all extents for this class
200: */
201: for (int i = 0; i < extentClasses.size(); i++) {
202: Class ec = (Class) extentClasses.get(i);
203: ClassDescriptor extCld = cld.getRepository()
204: .getDescriptorFor(ec);
205: classes.addAll(getExtentClasses(extCld));
206: }
207: }
208:
209: return classes;
210: }
211:
212: /**
213: * Searches the class descriptor for the ojbConcrete class attribute
214: * if it finds the concrete class attribute, append a where clause which
215: * specifies we can load all classes that are this type or extents of this type.
216: * @param cld
217: * @param crit
218: * @return the passed in Criteria object + optionally and'ed criteria with OR'd class
219: * type discriminators.
220: */
221: private static Criteria addCriteriaForOjbConcreteClasses(
222: ClassDescriptor cld, Criteria crit) {
223: /**
224: * 1. check if this class has a ojbConcreteClass attribute
225: */
226: Criteria concreteClassDiscriminator = null;
227: Collection classes = getExtentClasses(cld);
228:
229: /**
230: * 1. create a new Criteria for objConcreteClass
231: */
232: if (!classes.isEmpty()) {
233: concreteClassDiscriminator = new Criteria();
234: if (classes.size() > 1) {
235: concreteClassDiscriminator = new Criteria();
236: concreteClassDiscriminator.addIn(
237: ClassDescriptor.OJB_CONCRETE_CLASS, classes);
238: } else {
239: concreteClassDiscriminator.addEqualTo(
240: ClassDescriptor.OJB_CONCRETE_CLASS, classes
241: .toArray()[0]);
242: }
243: }
244:
245: /**
246: * 2. only add the AND (objConcreteClass = "some.class" OR....) if we've actually found concrete
247: * classes.
248: */
249: if (concreteClassDiscriminator != null) {
250: /**
251: * it's possible there is no criteria attached to the query, and in this
252: * case we still have to add the IN/EqualTo criteria for the concrete class type
253: * so check if the crit is null and then create a blank one if needed.
254: */
255: if (crit == null) {
256: crit = new Criteria();
257: }
258:
259: crit.addAndCriteria(concreteClassDiscriminator);
260: }
261: /**
262: * will just return the passed in criteria if no OJB concrete class is attribute is found.
263: */
264: return crit;
265: }
266:
267: }
|