1 package org.apache.ojb.broker.accesslayer; 2 3 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.PersistenceBroker; 29 import org.apache.ojb.broker.accesslayer.conversions.FieldConversion; 30 import org.apache.ojb.broker.core.PersistenceBrokerImpl; 31 import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl; 32 import org.apache.ojb.broker.metadata.ClassDescriptor; 33 import org.apache.ojb.broker.metadata.CollectionDescriptor; 34 import org.apache.ojb.broker.metadata.FieldDescriptor; 35 import org.apache.ojb.broker.metadata.FieldHelper; 36 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor; 37 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField; 38 import org.apache.ojb.broker.query.Criteria; 39 import org.apache.ojb.broker.query.Query; 40 import org.apache.ojb.broker.query.QueryByMtoNCriteria; 41 import org.apache.ojb.broker.query.ReportQueryByMtoNCriteria; 42 43 49 public class MtoNCollectionPrefetcher extends CollectionPrefetcher 50 { 51 52 56 public MtoNCollectionPrefetcher(PersistenceBrokerImpl aBroker, ObjectReferenceDescriptor anOrd) 57 { 58 super(aBroker, anOrd); 59 } 60 61 64 public void prefetchRelationship(Collection owners) 65 { 66 Query[] queries; 67 Query[] mnQueries; 68 Collection children = new ArrayList (); 69 Collection mnImplementors = new ArrayList (); 70 71 queries = buildPrefetchQueries(owners, children); 72 mnQueries = buildMtoNImplementorQueries(owners, children); 73 74 for (int i = 0; i < queries.length; i++) 75 { 76 Iterator iter = getBroker().getIteratorByQuery(queries[i]); 77 while (iter.hasNext()) 78 { 79 Object aChild = iter.next(); 80 81 if (!children.contains(aChild)) 83 { 84 children.add(aChild); 85 } 86 } 87 88 Iterator mnIter = getBroker().getReportQueryIteratorByQuery(mnQueries[i]); 89 while (mnIter.hasNext()) 90 { 91 mnImplementors.add(mnIter.next()); 92 } 93 } 94 95 associateBatched(owners, children, mnImplementors); 96 } 97 98 111 protected Query buildPrefetchQuery(Collection ids) 112 { 113 CollectionDescriptor cds = getCollectionDescriptor(); 114 String [] indFkCols = getFksToThisClass(); 115 String [] indItemFkCols = getFksToItemClass(); 116 FieldDescriptor[] itemPkFields = getItemClassDescriptor().getPkFields(); 117 118 Criteria crit = buildPrefetchCriteria(ids, indFkCols, indItemFkCols, itemPkFields); 119 120 129 return new QueryByMtoNCriteria(cds.getItemClass(), cds.getIndirectionTable(), crit, false); 130 } 131 132 136 protected Query buildMtoNImplementorQuery(Collection ids) 137 { 138 String [] indFkCols = getFksToThisClass(); 139 String [] indItemFkCols = getFksToItemClass(); 140 FieldDescriptor[] pkFields = getOwnerClassDescriptor().getPkFields(); 141 FieldDescriptor[] itemPkFields = getItemClassDescriptor().getPkFields(); 142 String [] cols = new String [indFkCols.length + indItemFkCols.length]; 143 int[] jdbcTypes = new int[indFkCols.length + indItemFkCols.length]; 144 145 System.arraycopy(indFkCols, 0, cols, 0, indFkCols.length); 147 System.arraycopy(indItemFkCols, 0, cols, indFkCols.length, indItemFkCols.length); 148 149 Criteria crit = buildPrefetchCriteria(ids, indFkCols, indItemFkCols, itemPkFields); 150 151 for (int i = 0; i < pkFields.length; i++) 153 { 154 jdbcTypes[i] = pkFields[i].getJdbcType().getType(); 155 } 156 for (int i = 0; i < itemPkFields.length; i++) 157 { 158 jdbcTypes[pkFields.length + i] = itemPkFields[i].getJdbcType().getType(); 159 } 160 161 ReportQueryByMtoNCriteria q = new ReportQueryByMtoNCriteria(getItemClassDescriptor().getClassOfObject(), cols, 162 crit, false); 163 q.setIndirectionTable(getCollectionDescriptor().getIndirectionTable()); 164 q.setJdbcTypes(jdbcTypes); 165 166 CollectionDescriptor cds = getCollectionDescriptor(); 167 if (!cds.getOrderBy().isEmpty()) 169 { 170 Iterator iter = cds.getOrderBy().iterator(); 171 while (iter.hasNext()) 172 { 173 q.addOrderBy((FieldHelper) iter.next()); 174 } 175 } 176 177 return q; 178 } 179 180 183 private String [] getFksToThisClass() 184 { 185 String indTable = getCollectionDescriptor().getIndirectionTable(); 186 String [] fks = getCollectionDescriptor().getFksToThisClass(); 187 String [] result = new String [fks.length]; 188 189 for (int i = 0; i < result.length; i++) 190 { 191 result[i] = indTable + "." + fks[i]; 192 } 193 194 return result; 195 } 196 197 200 private String [] getFksToItemClass() 201 { 202 String indTable = getCollectionDescriptor().getIndirectionTable(); 203 String [] fks = getCollectionDescriptor().getFksToItemClass(); 204 String [] result = new String [fks.length]; 205 206 for (int i = 0; i < result.length; i++) 207 { 208 result[i] = indTable + "." + fks[i]; 209 } 210 211 return result; 212 } 213 214 219 protected Query[] buildMtoNImplementorQueries(Collection owners, Collection children) 220 { 221 ClassDescriptor cld = getOwnerClassDescriptor(); 222 PersistenceBroker pb = getBroker(); 223 Collection queries = new ArrayList (owners.size()); 226 Collection idsSubset = new HashSet (owners.size()); 227 Object owner; 229 Identity id; 230 231 Iterator iter = owners.iterator(); 232 while (iter.hasNext()) 233 { 234 owner = iter.next(); 235 id = pb.serviceIdentity().buildIdentity(cld, owner); 236 idsSubset.add(id); 237 if (idsSubset.size() == pkLimit) 238 { 239 queries.add(buildMtoNImplementorQuery(idsSubset)); 240 idsSubset.clear(); 241 } 242 } 243 244 if (idsSubset.size() > 0) 245 { 246 queries.add(buildMtoNImplementorQuery(idsSubset)); 247 } 248 249 return (Query[]) queries.toArray(new Query[queries.size()]); 250 } 251 252 260 private Criteria buildPrefetchCriteria(Collection ids, String [] fkCols, String [] itemFkCols, 261 FieldDescriptor[] itemPkFields) 262 { 263 if (fkCols.length == 1 && itemFkCols.length == 1) 264 { 265 return buildPrefetchCriteriaSingleKey(ids, fkCols[0], itemFkCols[0], itemPkFields[0]); 266 } 267 else 268 { 269 return buildPrefetchCriteriaMultipleKeys(ids, fkCols, itemFkCols, itemPkFields); 270 } 271 272 } 273 274 283 private Criteria buildPrefetchCriteriaSingleKey(Collection ids, String fkCol, String itemFkCol, 284 FieldDescriptor itemPkField) 285 { 286 Criteria crit = new Criteria(); 287 ArrayList values = new ArrayList (ids.size()); 288 Iterator iter = ids.iterator(); 289 Identity id; 290 291 while (iter.hasNext()) 292 { 293 id = (Identity) iter.next(); 294 values.add(id.getPrimaryKeyValues()[0]); 295 } 296 297 switch (values.size()) 298 { 299 case 0 : 300 break; 301 case 1 : 302 crit.addEqualTo(fkCol, values.get(0)); 303 break; 304 default : 305 crit.addIn(fkCol, values); 307 break; 308 } 309 310 crit.addEqualToField(itemPkField.getAttributeName(), itemFkCol); 311 312 return crit; 313 } 314 315 324 private Criteria buildPrefetchCriteriaMultipleKeys(Collection ids, String [] fkCols, String [] itemFkCols, 325 FieldDescriptor[] itemPkFields) 326 { 327 Criteria crit = new Criteria(); 328 Criteria critValue = new Criteria(); 329 Iterator iter = ids.iterator(); 330 331 for (int i = 0; i < itemPkFields.length; i++) 332 { 333 crit.addEqualToField(itemPkFields[i].getAttributeName(), itemFkCols[i]); 334 } 335 336 while (iter.hasNext()) 337 { 338 Criteria c = new Criteria(); 339 Identity id = (Identity) iter.next(); 340 Object [] val = id.getPrimaryKeyValues(); 341 342 for (int i = 0; i < val.length; i++) 343 { 344 345 if (val[i] == null) 346 { 347 c.addIsNull(fkCols[i]); 348 } 349 else 350 { 351 c.addEqualTo(fkCols[i], val[i]); 352 } 353 354 } 355 356 critValue.addOrCriteria(c); 357 } 358 359 crit.addAndCriteria(critValue); 360 return crit; 361 } 362 363 368 private FieldConversion[] getPkFieldConversion(ClassDescriptor cld) 369 { 370 FieldDescriptor[] pks = cld.getPkFields(); 371 FieldConversion[] fc = new FieldConversion[pks.length]; 372 373 for (int i= 0; i < pks.length; i++) 374 { 375 fc[i] = pks[i].getFieldConversion(); 376 } 377 378 return fc; 379 } 380 381 386 private Object [] convert(FieldConversion[] fcs, Object [] values) 387 { 388 Object [] convertedValues = new Object [values.length]; 389 390 for (int i= 0; i < values.length; i++) 391 { 392 convertedValues[i] = fcs[i].sqlToJava(values[i]); 393 } 394 395 return convertedValues; 396 } 397 398 411 protected void associateBatched(Collection owners, Collection children, Collection mToNImplementors) 412 { 413 CollectionDescriptor cds = getCollectionDescriptor(); 414 PersistentField field = cds.getPersistentField(); 415 PersistenceBroker pb = getBroker(); 416 Class ownerTopLevelClass = pb.getTopLevelClass(getOwnerClassDescriptor().getClassOfObject()); 417 Class childTopLevelClass = pb.getTopLevelClass(getItemClassDescriptor().getClassOfObject()); 418 Class collectionClass = cds.getCollectionClass(); HashMap childMap = new HashMap (); 420 HashMap ownerIdsToLists = new HashMap (); 421 FieldConversion[] ownerFc = getPkFieldConversion(getOwnerClassDescriptor()); 422 FieldConversion[] childFc = getPkFieldConversion(getItemClassDescriptor()); 423 424 for (Iterator it = owners.iterator(); it.hasNext();) 426 { 427 Object owner = it.next(); 428 Identity oid = pb.serviceIdentity().buildIdentity(owner); 429 ownerIdsToLists.put(oid, new ArrayList ()); 430 } 431 432 for (Iterator it = children.iterator(); it.hasNext();) 434 { 435 Object child = it.next(); 436 Identity oid = pb.serviceIdentity().buildIdentity(child); 437 childMap.put(oid, child); 438 } 439 440 int ownerPkLen = getOwnerClassDescriptor().getPkFields().length; 441 int childPkLen = getItemClassDescriptor().getPkFields().length; 442 Object [] ownerPk = new Object [ownerPkLen]; 443 Object [] childPk = new Object [childPkLen]; 444 445 for (Iterator it = mToNImplementors.iterator(); it.hasNext();) 447 { 448 Object [] mToN = (Object []) it.next(); 449 System.arraycopy(mToN, 0, ownerPk, 0, ownerPkLen); 450 System.arraycopy(mToN, ownerPkLen, childPk, 0, childPkLen); 451 452 ownerPk = convert(ownerFc, ownerPk); 454 childPk = convert(childFc, childPk); 455 456 Identity ownerId = pb.serviceIdentity().buildIdentity(null, ownerTopLevelClass, ownerPk); 457 Identity childId = pb.serviceIdentity().buildIdentity(null, childTopLevelClass, childPk); 458 459 Collection list = (Collection ) ownerIdsToLists.get(ownerId); 461 Object child = childMap.get(childId); 462 list.add(child); 463 } 464 465 for (Iterator it = owners.iterator(); it.hasNext();) 467 { 468 Object result; 469 Object owner = it.next(); 470 Identity ownerId = pb.serviceIdentity().buildIdentity(owner); 471 472 List list = (List ) ownerIdsToLists.get(ownerId); 473 474 if ((collectionClass == null) && field.getType().isArray()) 475 { 476 int length = list.size(); 477 Class itemtype = field.getType().getComponentType(); 478 479 result = Array.newInstance(itemtype, length); 480 481 for (int j = 0; j < length; j++) 482 { 483 Array.set(result, j, list.get(j)); 484 } 485 } 486 else 487 { 488 ManageableCollection col = createCollection(cds, collectionClass); 489 490 for (Iterator it2 = list.iterator(); it2.hasNext();) 491 { 492 col.ojbAdd(it2.next()); 493 } 494 result = col; 495 } 496 497 Object value = field.get(owner); 498 if ((value instanceof CollectionProxyDefaultImpl) && (result instanceof Collection )) 499 { 500 ((CollectionProxyDefaultImpl) value).setData((Collection ) result); 501 } 502 else 503 { 504 field.set(owner, result); 505 } 506 } 507 508 } 509 } 510 | Popular Tags |