1 | |
package org.apache.ojb.broker.accesslayer; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
import java.lang.reflect.Array; |
19 | |
import java.util.ArrayList; |
20 | |
import java.util.Collection; |
21 | |
import java.util.HashMap; |
22 | |
import java.util.HashSet; |
23 | |
import java.util.Iterator; |
24 | |
import java.util.List; |
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 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
public class CollectionPrefetcher extends RelationshipPrefetcherImpl |
54 | |
{ |
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
public CollectionPrefetcher(PersistenceBrokerImpl aBroker, ObjectReferenceDescriptor anOrd) |
63 | |
{ |
64 | |
super(aBroker, anOrd); |
65 | |
} |
66 | |
|
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
protected Query[] buildPrefetchQueries(Collection owners, Collection children) |
73 | |
{ |
74 | |
ClassDescriptor cld = getOwnerClassDescriptor(); |
75 | |
Class topLevelClass = getBroker().getTopLevelClass(cld.getClassOfObject()); |
76 | |
BrokerHelper helper = getBroker().serviceBrokerHelper(); |
77 | |
Collection queries = new ArrayList(owners.size()); |
78 | |
Collection idsSubset = new HashSet(owners.size()); |
79 | |
Object[] fkValues; |
80 | |
Object owner; |
81 | |
Identity id; |
82 | |
|
83 | |
Iterator 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 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
protected Query buildPrefetchQuery(Collection ids) |
111 | |
{ |
112 | |
CollectionDescriptor cds = getCollectionDescriptor(); |
113 | |
QueryByCriteria query = buildPrefetchQuery(ids, cds.getForeignKeyFieldDescriptors(getItemClassDescriptor())); |
114 | |
|
115 | |
|
116 | |
if (!cds.getOrderBy().isEmpty()) |
117 | |
{ |
118 | |
Iterator 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 | |
|
130 | |
|
131 | |
protected void associateBatched(Collection owners, Collection children) |
132 | |
{ |
133 | |
CollectionDescriptor cds = getCollectionDescriptor(); |
134 | |
PersistentField field = cds.getPersistentField(); |
135 | |
PersistenceBroker pb = getBroker(); |
136 | |
Class ownerTopLevelClass = pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject()); |
137 | |
Class collectionClass = cds.getCollectionClass(); |
138 | |
HashMap ownerIdsToLists = new HashMap(owners.size()); |
139 | |
|
140 | |
IdentityFactory identityFactory = pb.serviceIdentity(); |
141 | |
|
142 | |
for (Iterator it = owners.iterator(); it.hasNext();) |
143 | |
{ |
144 | |
Object owner = it.next(); |
145 | |
ownerIdsToLists.put(identityFactory.buildIdentity(getOwnerClassDescriptor(), owner), new ArrayList()); |
146 | |
} |
147 | |
|
148 | |
|
149 | |
for (Iterator it = children.iterator(); it.hasNext();) |
150 | |
{ |
151 | |
Object child = it.next(); |
152 | |
|
153 | |
ClassDescriptor cld = getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(child)); |
154 | |
|
155 | |
Object[] fkValues = cds.getForeignKeyValues(child, cld); |
156 | |
Identity ownerId = identityFactory.buildIdentity(null, ownerTopLevelClass, fkValues); |
157 | |
List list = (List) ownerIdsToLists.get(ownerId); |
158 | |
if (list != null) |
159 | |
{ |
160 | |
list.add(child); |
161 | |
} |
162 | |
} |
163 | |
|
164 | |
|
165 | |
for (Iterator it = owners.iterator(); it.hasNext();) |
166 | |
{ |
167 | |
Object result; |
168 | |
Object owner = it.next(); |
169 | |
Identity ownerId = identityFactory.buildIdentity(owner); |
170 | |
List list = (List) ownerIdsToLists.get(ownerId); |
171 | |
|
172 | |
if ((collectionClass == null) && field.getType().isArray()) |
173 | |
{ |
174 | |
int length = list.size(); |
175 | |
Class 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 it2 = list.iterator(); it2.hasNext();) |
186 | |
{ |
187 | |
col.ojbAdd(it2.next()); |
188 | |
} |
189 | |
result = col; |
190 | |
} |
191 | |
|
192 | |
Object value = field.get(owner); |
193 | |
if ((value instanceof CollectionProxyDefaultImpl) && (result instanceof Collection)) |
194 | |
{ |
195 | |
((CollectionProxyDefaultImpl) value).setData((Collection) result); |
196 | |
} |
197 | |
else |
198 | |
{ |
199 | |
field.set(owner, result); |
200 | |
} |
201 | |
} |
202 | |
} |
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
protected ManageableCollection createCollection(CollectionDescriptor desc, Class collectionClass) |
214 | |
{ |
215 | |
Class 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 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 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 | |
} |