001: package org.apache.ojb.broker.accesslayer;
002:
003: /* Copyright 2003-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.ArrayList;
019: import java.util.Collection;
020: import java.util.Iterator;
021:
022: import org.apache.ojb.broker.Identity;
023: import org.apache.ojb.broker.PersistenceBrokerFactory;
024: import org.apache.ojb.broker.core.PersistenceBrokerConfiguration;
025: import org.apache.ojb.broker.core.PersistenceBrokerImpl;
026: import org.apache.ojb.broker.metadata.ClassDescriptor;
027: import org.apache.ojb.broker.metadata.DescriptorRepository;
028: import org.apache.ojb.broker.metadata.FieldDescriptor;
029: import org.apache.ojb.broker.query.Criteria;
030: import org.apache.ojb.broker.query.Query;
031: import org.apache.ojb.broker.query.QueryByCriteria;
032: import org.apache.ojb.broker.query.QueryFactory;
033: import org.apache.ojb.broker.util.configuration.ConfigurationException;
034: import org.apache.ojb.broker.util.logging.Logger;
035: import org.apache.ojb.broker.util.logging.LoggerFactory;
036:
037: /**
038: * Abstract Prefetcher.
039: * @author <a href="mailto:olegnitz@apache.org">Oleg Nitz</a>
040: * @version $Id: BasePrefetcher.java,v 1.10.2.3 2005/12/29 22:47:48 tomdz Exp $
041: */
042: public abstract class BasePrefetcher implements RelationshipPrefetcher {
043: /** The numer of columns to query for. */
044: protected static final int IN_LIMIT = getPrefetchInLimit();
045:
046: private Logger logger;
047: private PersistenceBrokerImpl broker;
048: /** Class descriptor for the item type. */
049: protected ClassDescriptor itemClassDesc;
050: /** Maximum number of pk's in one query. */
051: protected final int pkLimit;
052:
053: /**
054: * Returns the number of column to query for, from the configuration.
055: *
056: * @return The prefetch limit
057: */
058: private static int getPrefetchInLimit() {
059: try {
060: PersistenceBrokerConfiguration config = (PersistenceBrokerConfiguration) PersistenceBrokerFactory
061: .getConfigurator().getConfigurationFor(null);
062:
063: return config.getSqlInLimit();
064: } catch (ConfigurationException e) {
065: return 200;
066: }
067: }
068:
069: /**
070: * Constructor for BasePrefetcher.
071: */
072: public BasePrefetcher(PersistenceBrokerImpl aBroker,
073: Class anItemClass) {
074: super ();
075: broker = aBroker;
076: itemClassDesc = aBroker.getDescriptorRepository()
077: .getDescriptorFor(anItemClass);
078: logger = LoggerFactory.getLogger(this .getClass());
079: pkLimit = getPrefetchInLimit()
080: / getItemClassDescriptor().getPkFields().length;
081: }
082:
083: /**
084: * The limit of objects loaded by one SQL query
085: */
086: public int getLimit() {
087: return pkLimit;
088: }
089:
090: /**
091: * associate the batched Children with their owner object <br>
092: */
093: protected abstract void associateBatched(Collection owners,
094: Collection children);
095:
096: /**
097: * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcher#prefetchRelationship(Collection)
098: */
099: public void prefetchRelationship(Collection owners) {
100: Query queries[];
101: Collection children = new ArrayList();
102:
103: queries = buildPrefetchQueries(owners, children);
104:
105: for (int i = 0; i < queries.length; i++) {
106: Iterator iter = getBroker().getIteratorByQuery(queries[i]);
107: while (iter.hasNext()) {
108: children.add(iter.next());
109: }
110: }
111:
112: // BRJ: performRetrieval of childrens references BEFORE associating with owners
113: // TODO: this is a quick fix !
114: getBroker().getReferenceBroker().performRetrievalTasks();
115:
116: associateBatched(owners, children);
117: }
118:
119: protected QueryByCriteria buildPrefetchQuery(Collection ids,
120: FieldDescriptor[] fields) {
121: return buildPrefetchQuery(getItemClassDescriptor()
122: .getClassOfObject(), ids, fields);
123: }
124:
125: /**
126: *
127: * @param ids collection of identities
128: * @param fields
129: * @return
130: */
131: protected Criteria buildPrefetchCriteria(Collection ids,
132: FieldDescriptor[] fields) {
133: if (fields.length == 1) {
134: return buildPrefetchCriteriaSingleKey(ids, fields[0]);
135: } else {
136: return buildPrefetchCriteriaMultipleKeys(ids, fields);
137: }
138:
139: }
140:
141: /**
142: *
143: * @param clazz
144: * @param ids collection of identities
145: * @param fields
146: * @return
147: */
148: protected QueryByCriteria buildPrefetchQuery(Class clazz,
149: Collection ids, FieldDescriptor[] fields) {
150: return QueryFactory.newQuery(clazz, buildPrefetchCriteria(ids,
151: fields));
152: }
153:
154: /**
155: * Build the Criteria using IN(...) for single keys
156: * @param ids collection of identities
157: * @param field
158: * @return Criteria
159: */
160: private Criteria buildPrefetchCriteriaSingleKey(Collection ids,
161: FieldDescriptor field) {
162: Criteria crit = new Criteria();
163: ArrayList values = new ArrayList(ids.size());
164: Iterator iter = ids.iterator();
165: Identity id;
166:
167: while (iter.hasNext()) {
168: id = (Identity) iter.next();
169: values.add(id.getPrimaryKeyValues()[0]);
170: }
171:
172: switch (values.size()) {
173: case 0:
174: break;
175: case 1:
176: crit.addEqualTo(field.getAttributeName(), values.get(0));
177: break;
178: default:
179: // create IN (...) for the single key field
180: crit.addIn(field.getAttributeName(), values);
181: break;
182: }
183:
184: return crit;
185: }
186:
187: /**
188: * Build the Criteria using multiple ORs
189: * @param ids collection of identities
190: * @param fields
191: * @return Criteria
192: */
193: private Criteria buildPrefetchCriteriaMultipleKeys(Collection ids,
194: FieldDescriptor fields[]) {
195: Criteria crit = new Criteria();
196: Iterator iter = ids.iterator();
197: Object[] val;
198: Identity id;
199:
200: while (iter.hasNext()) {
201: Criteria c = new Criteria();
202: id = (Identity) iter.next();
203: val = id.getPrimaryKeyValues();
204: for (int i = 0; i < val.length; i++) {
205: if (val[i] == null) {
206: c.addIsNull(fields[i].getAttributeName());
207: } else {
208: c.addEqualTo(fields[i].getAttributeName(), val[i]);
209: }
210: }
211: crit.addOrCriteria(c);
212: }
213:
214: return crit;
215: }
216:
217: /**
218: * Return the DescriptorRepository
219: */
220: protected DescriptorRepository getDescriptorRepository() {
221: return getBroker().getDescriptorRepository();
222: }
223:
224: /**
225: * Returns the ClassDescriptor of the item Class
226: * @return ClassDescriptor
227: */
228: public ClassDescriptor getItemClassDescriptor() {
229: return itemClassDesc;
230: }
231:
232: protected abstract Query[] buildPrefetchQueries(Collection owners,
233: Collection children);
234:
235: /**
236: * Returns the broker.
237: * @return PersistenceBrokerImpl
238: */
239: protected PersistenceBrokerImpl getBroker() {
240: return broker;
241: }
242:
243: /**
244: * Returns the logger.
245: * @return Logger
246: */
247: protected Logger getLogger() {
248: return logger;
249: }
250: }
|