KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > CollectionPrefetcher


1 package org.apache.ojb.broker.accesslayer;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.lang.reflect.Array JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.apache.ojb.broker.Identity;
27 import org.apache.ojb.broker.ManageableCollection;
28 import org.apache.ojb.broker.OJBRuntimeException;
29 import org.apache.ojb.broker.PersistenceBroker;
30 import org.apache.ojb.broker.IdentityFactory;
31 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
32 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
33 import org.apache.ojb.broker.core.proxy.ProxyHelper;
34 import org.apache.ojb.broker.metadata.ClassDescriptor;
35 import org.apache.ojb.broker.metadata.CollectionDescriptor;
36 import org.apache.ojb.broker.metadata.FieldHelper;
37 import org.apache.ojb.broker.metadata.MetadataException;
38 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
39 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
40 import org.apache.ojb.broker.query.Query;
41 import org.apache.ojb.broker.query.QueryByCriteria;
42 import org.apache.ojb.broker.util.BrokerHelper;
43 import org.apache.ojb.broker.util.collections.RemovalAwareCollection;
44 import org.apache.ojb.broker.util.collections.RemovalAwareList;
45 import org.apache.ojb.broker.util.collections.RemovalAwareSet;
46
47 /**
48  * Relationship Prefetcher for Collections.
49  *
50  * @author <a HREF="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
51  * @version $Id: CollectionPrefetcher.java,v 1.29.2.5 2005/12/21 22:22:58 tomdz Exp $
52  */

53 public class CollectionPrefetcher extends RelationshipPrefetcherImpl
54 {
55
56     /**
57      * Constructor for CollectionPrefetcher.
58      *
59      * @param aBroker
60      * @param anOrd
61      */

62     public CollectionPrefetcher(PersistenceBrokerImpl aBroker, ObjectReferenceDescriptor anOrd)
63     {
64         super(aBroker, anOrd);
65     }
66
67     /**
68      * Build the multiple queries for one relationship because of limitation of IN(...)
69      *
70      * @param owners Collection containing all objects of the ONE side
71      */

72     protected Query[] buildPrefetchQueries(Collection JavaDoc owners, Collection JavaDoc children)
73     {
74         ClassDescriptor cld = getOwnerClassDescriptor();
75         Class JavaDoc topLevelClass = getBroker().getTopLevelClass(cld.getClassOfObject());
76         BrokerHelper helper = getBroker().serviceBrokerHelper();
77         Collection JavaDoc queries = new ArrayList JavaDoc(owners.size());
78         Collection JavaDoc idsSubset = new HashSet JavaDoc(owners.size());
79         Object JavaDoc[] fkValues;
80         Object JavaDoc owner;
81         Identity id;
82
83         Iterator JavaDoc iter = owners.iterator();
84         while (iter.hasNext())
85         {
86             owner = iter.next();
87             fkValues = helper.extractValueArray(helper.getKeyValues(cld, owner));
88             id = getBroker().serviceIdentity().buildIdentity(null, topLevelClass, fkValues);
89             idsSubset.add(id);
90             if (idsSubset.size() == pkLimit)
91             {
92                 queries.add(buildPrefetchQuery(idsSubset));
93                 idsSubset.clear();
94             }
95         }
96
97         if (idsSubset.size() > 0)
98         {
99             queries.add(buildPrefetchQuery(idsSubset));
100         }
101
102         return (Query[]) queries.toArray(new Query[queries.size()]);
103     }
104
105     /**
106      * Build the query to perform a batched read get orderBy settings from CollectionDescriptor
107      *
108      * @param ids Collection containing all identities of objects of the ONE side
109      */

110     protected Query buildPrefetchQuery(Collection JavaDoc ids)
111     {
112         CollectionDescriptor cds = getCollectionDescriptor();
113         QueryByCriteria query = buildPrefetchQuery(ids, cds.getForeignKeyFieldDescriptors(getItemClassDescriptor()));
114
115         // check if collection must be ordered
116
if (!cds.getOrderBy().isEmpty())
117         {
118             Iterator JavaDoc iter = cds.getOrderBy().iterator();
119             while (iter.hasNext())
120             {
121                 query.addOrderBy((FieldHelper) iter.next());
122             }
123         }
124
125         return query;
126     }
127
128     /**
129      * associate the batched Children with their owner object loop over children
130      */

131     protected void associateBatched(Collection JavaDoc owners, Collection JavaDoc children)
132     {
133         CollectionDescriptor cds = getCollectionDescriptor();
134         PersistentField field = cds.getPersistentField();
135         PersistenceBroker pb = getBroker();
136         Class JavaDoc ownerTopLevelClass = pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject());
137         Class JavaDoc collectionClass = cds.getCollectionClass(); // this collection type will be used:
138
HashMap JavaDoc ownerIdsToLists = new HashMap JavaDoc(owners.size());
139
140         IdentityFactory identityFactory = pb.serviceIdentity();
141         // initialize the owner list map
142
for (Iterator JavaDoc it = owners.iterator(); it.hasNext();)
143         {
144             Object JavaDoc owner = it.next();
145             ownerIdsToLists.put(identityFactory.buildIdentity(getOwnerClassDescriptor(), owner), new ArrayList JavaDoc());
146         }
147
148         // build the children lists for the owners
149
for (Iterator JavaDoc it = children.iterator(); it.hasNext();)
150         {
151             Object JavaDoc child = it.next();
152             // BRJ: use cld for real class, relatedObject could be Proxy
153
ClassDescriptor cld = getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(child));
154
155             Object JavaDoc[] fkValues = cds.getForeignKeyValues(child, cld);
156             Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, fkValues);
157             List JavaDoc list = (List JavaDoc) ownerIdsToLists.get(ownerId);
158             if (list != null)
159             {
160                 list.add(child);
161             }
162         }
163
164         // connect children list to owners
165
for (Iterator JavaDoc it = owners.iterator(); it.hasNext();)
166         {
167             Object JavaDoc result;
168             Object JavaDoc owner = it.next();
169             Identity ownerId = identityFactory.buildIdentity(owner);
170             List JavaDoc list = (List JavaDoc) ownerIdsToLists.get(ownerId);
171
172             if ((collectionClass == null) && field.getType().isArray())
173             {
174                 int length = list.size();
175                 Class JavaDoc itemtype = field.getType().getComponentType();
176                 result = Array.newInstance(itemtype, length);
177                 for (int j = 0; j < length; j++)
178                 {
179                     Array.set(result, j, list.get(j));
180                 }
181             }
182             else
183             {
184                 ManageableCollection col = createCollection(cds, collectionClass);
185                 for (Iterator JavaDoc it2 = list.iterator(); it2.hasNext();)
186                 {
187                     col.ojbAdd(it2.next());
188                 }
189                 result = col;
190             }
191
192             Object JavaDoc value = field.get(owner);
193             if ((value instanceof CollectionProxyDefaultImpl) && (result instanceof Collection JavaDoc))
194             {
195                 ((CollectionProxyDefaultImpl) value).setData((Collection JavaDoc) result);
196             }
197             else
198             {
199                 field.set(owner, result);
200             }
201         }
202     }
203
204     /**
205      * Create a collection object of the given collection type. If none has been given,
206      * OJB uses RemovalAwareList, RemovalAwareSet, or RemovalAwareCollection depending
207      * on the field type.
208      *
209      * @param desc The collection descriptor
210      * @param collectionClass The collection class specified in the collection-descriptor
211      * @return The collection object
212      */

213     protected ManageableCollection createCollection(CollectionDescriptor desc, Class JavaDoc collectionClass)
214     {
215         Class JavaDoc fieldType = desc.getPersistentField().getType();
216         ManageableCollection col;
217
218         if (collectionClass == null)
219         {
220             if (ManageableCollection.class.isAssignableFrom(fieldType))
221             {
222                 try
223                 {
224                     col = (ManageableCollection)fieldType.newInstance();
225                 }
226                 catch (Exception JavaDoc e)
227                 {
228                     throw new OJBRuntimeException("Cannot instantiate the default collection type "+fieldType.getName()+" of collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
229                 }
230             }
231             else if (fieldType.isAssignableFrom(RemovalAwareCollection.class))
232             {
233                 col = new RemovalAwareCollection();
234             }
235             else if (fieldType.isAssignableFrom(RemovalAwareList.class))
236             {
237                 col = new RemovalAwareList();
238             }
239             else if (fieldType.isAssignableFrom(RemovalAwareSet.class))
240             {
241                 col = new RemovalAwareSet();
242             }
243             else
244             {
245                 throw new MetadataException("Cannot determine a default collection type for collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
246             }
247         }
248         else
249         {
250             try
251             {
252                 col = (ManageableCollection)collectionClass.newInstance();
253             }
254             catch (Exception JavaDoc e)
255             {
256                 throw new OJBRuntimeException("Cannot instantiate the collection class "+collectionClass.getName()+" of collection "+desc.getAttributeName()+" in type "+desc.getClassDescriptor().getClassNameOfObject());
257             }
258         }
259         return col;
260     }
261
262     protected CollectionDescriptor getCollectionDescriptor()
263     {
264         return (CollectionDescriptor) getObjectReferenceDescriptor();
265     }
266 }
267
Popular Tags