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