001: package org.apache.ojb.broker.accesslayer;
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.ArrayList;
019: import java.util.Collection;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Iterator;
023:
024: import org.apache.ojb.broker.Identity;
025: import org.apache.ojb.broker.PersistenceBroker;
026: import org.apache.ojb.broker.cache.ObjectCache;
027: import org.apache.ojb.broker.core.PersistenceBrokerImpl;
028: import org.apache.ojb.broker.metadata.ClassDescriptor;
029: import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
030: import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
031: import org.apache.ojb.broker.query.Query;
032:
033: /**
034: * Relationship Prefetcher for References.
035: *
036: * @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
037: * @version $Id: ReferencePrefetcher.java,v 1.20.2.3 2005/12/21 22:22:58 tomdz Exp $
038: */
039: public class ReferencePrefetcher extends RelationshipPrefetcherImpl {
040:
041: /**
042: * Constructor for ReferencePrefetcher.
043: * @param aBroker
044: * @param anOrd
045: */
046: public ReferencePrefetcher(PersistenceBrokerImpl aBroker,
047: ObjectReferenceDescriptor anOrd) {
048: super (aBroker, anOrd);
049: }
050:
051: /**
052: * Associate the batched Children with their owner object.
053: * Loop over owners
054: */
055: protected void associateBatched(Collection owners,
056: Collection children) {
057: ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
058: ClassDescriptor cld = getOwnerClassDescriptor();
059: Object owner;
060: Object relatedObject;
061: Object fkValues[];
062: Identity id;
063: PersistenceBroker pb = getBroker();
064: PersistentField field = ord.getPersistentField();
065: Class topLevelClass = pb.getTopLevelClass(ord.getItemClass());
066: HashMap childrenMap = new HashMap(children.size());
067:
068: for (Iterator it = children.iterator(); it.hasNext();) {
069: relatedObject = it.next();
070: childrenMap.put(pb.serviceIdentity().buildIdentity(
071: relatedObject), relatedObject);
072: }
073:
074: for (Iterator it = owners.iterator(); it.hasNext();) {
075: owner = it.next();
076: fkValues = ord.getForeignKeyValues(owner, cld);
077: if (isNull(fkValues)) {
078: field.set(owner, null);
079: continue;
080: }
081: id = pb.serviceIdentity().buildIdentity(null,
082: topLevelClass, fkValues);
083: relatedObject = childrenMap.get(id);
084: field.set(owner, relatedObject);
085: }
086: }
087:
088: private boolean isNull(Object[] arr) {
089: for (int i = 0; i < arr.length; i++) {
090: if (arr[i] != null) {
091: return false;
092: }
093: }
094: return true;
095: }
096:
097: /**
098: * Build the multiple queries for one relationship because of limitation of IN(...)
099: * @param owners Collection containing all objects of the ONE side
100: * @param children Collection where related objects found in the cache should be added.
101: */
102: protected Query[] buildPrefetchQueries(Collection owners,
103: Collection children) {
104: ClassDescriptor cld = getOwnerClassDescriptor();
105: ObjectReferenceDescriptor ord = getObjectReferenceDescriptor();
106: Collection queries = new ArrayList(owners.size());
107: Collection idsSubset = new HashSet(owners.size());
108: Iterator iter = owners.iterator();
109: Class topLevelClass = getBroker().getTopLevelClass(
110: ord.getItemClass());
111: Object[] fkValues;
112: Object owner;
113: Identity id;
114: PersistenceBroker pb = getBroker();
115: ObjectCache cache = pb.serviceObjectCache();
116:
117: while (iter.hasNext()) {
118: owner = iter.next();
119: fkValues = ord.getForeignKeyValues(owner, cld);
120: if (isNull(fkValues)) {
121: continue;
122: }
123: id = pb.serviceIdentity().buildIdentity(null,
124: topLevelClass, fkValues);
125: if (cache.lookup(id) != null) {
126: children.add(pb.getObjectByIdentity(id));
127: continue;
128: }
129: idsSubset.add(id);
130: if (idsSubset.size() == pkLimit) {
131: queries.add(buildPrefetchQuery(idsSubset));
132: idsSubset.clear();
133: }
134: }
135:
136: if (idsSubset.size() > 0) {
137: queries.add(buildPrefetchQuery(idsSubset));
138: }
139:
140: return (Query[]) queries.toArray(new Query[queries.size()]);
141: }
142:
143: /**
144: * @see org.apache.ojb.broker.accesslayer.RelationshipPrefetcherImpl#buildPrefetchCriteria(java.util.Collection, org.apache.ojb.broker.metadata.FieldDescriptor[])
145: */
146: protected Query buildPrefetchQuery(Collection ids) {
147: return buildPrefetchQuery(ids, getItemClassDescriptor()
148: .getPkFields());
149: }
150: }
|