1 56 package org.objectstyle.cayenne.map; 57 58 import java.util.ArrayList ; 59 import java.util.Collection ; 60 import java.util.Collections ; 61 import java.util.HashMap ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 import java.util.Map ; 65 66 import org.apache.commons.collections.collection.CompositeCollection; 67 import org.apache.log4j.Logger; 68 import org.objectstyle.cayenne.CayenneRuntimeException; 69 import org.objectstyle.cayenne.DataObject; 70 import org.objectstyle.cayenne.ObjectId; 71 import org.objectstyle.cayenne.TempObjectId; 72 import org.objectstyle.cayenne.client.ClientEntityResolver; 73 import org.objectstyle.cayenne.conf.Configuration; 74 import org.objectstyle.cayenne.distribution.GlobalID; 75 import org.objectstyle.cayenne.query.ProcedureQuery; 76 import org.objectstyle.cayenne.query.Query; 77 78 90 public class EntityResolver implements MappingNamespace { 91 92 private static final Logger logObj = Logger.getLogger(EntityResolver.class); 93 94 protected boolean indexedByClass; 95 protected Map queryCache; 96 protected Map dbEntityCache; 97 protected Map objEntityCache; 98 protected Map procedureCache; 99 protected List maps; 100 protected List mapsRef; 101 protected Map entityInheritanceCache; 102 103 106 public EntityResolver() { 107 this.indexedByClass = true; 108 this.maps = new ArrayList (); 109 this.mapsRef = Collections.unmodifiableList(maps); 110 this.queryCache = new HashMap (); 111 this.dbEntityCache = new HashMap (); 112 this.objEntityCache = new HashMap (); 113 this.procedureCache = new HashMap (); 114 this.entityInheritanceCache = new HashMap (); 115 } 116 117 120 public EntityResolver(Collection dataMaps) { 121 this(); 122 this.maps.addAll(dataMaps); this.constructCache(); 124 } 125 126 131 public GlobalID convertToGlobalID(ObjectId id) { 132 ObjEntity entity = lookupObjEntity(id.getObjectClass()); 133 if (entity == null) { 134 throw new CayenneRuntimeException("Unmapped object class:" 135 + id.getObjectClass().getName()); 136 } 137 138 if (id instanceof TempObjectId) { 139 return new GlobalID(entity.getName(), ((TempObjectId) id).getKey()); 140 } 141 else { 142 return new GlobalID(entity.getName(), id.getIdSnapshot()); 143 } 144 } 145 146 151 public ObjectId convertToObjectID(GlobalID id) { 152 ObjEntity entity = lookupObjEntity(id.getEntityName()); 153 154 if (entity == null) { 155 throw new CayenneRuntimeException("Unknown entity:" + id.getEntityName()); 156 } 157 158 Class objectClass = entity.getJavaClass(Thread 159 .currentThread() 160 .getContextClassLoader()); 161 return (id.isTemporary()) 162 ? new TempObjectId(objectClass, id.getKey()) 163 : new ObjectId(objectClass, id.getObjectIdKeys()); 164 } 165 166 171 public ClientEntityResolver getClientEntityResolver() { 172 Map entityNameByClientClass = new HashMap (); 174 175 Iterator it = getObjEntities().iterator(); 176 while (it.hasNext()) { 177 ObjEntity entity = (ObjEntity) it.next(); 178 String clientClassName = entity.getClientClassName(); 179 if (clientClassName == null) { 180 clientClassName = entity.getClassName(); 181 } 182 183 entityNameByClientClass.put(clientClassName, entity.getName()); 184 } 185 186 return new ClientEntityResolver(entityNameByClientClass); 187 } 188 189 192 public Collection getDbEntities() { 193 CompositeCollection c = new CompositeCollection(); 194 Iterator it = getDataMaps().iterator(); 195 while (it.hasNext()) { 196 DataMap map = (DataMap) it.next(); 197 c.addComposited(map.getDbEntities()); 198 } 199 200 return c; 201 } 202 203 public Collection getObjEntities() { 204 CompositeCollection c = new CompositeCollection(); 205 Iterator it = getDataMaps().iterator(); 206 while (it.hasNext()) { 207 DataMap map = (DataMap) it.next(); 208 c.addComposited(map.getObjEntities()); 209 } 210 211 return c; 212 } 213 214 public Collection getProcedures() { 215 CompositeCollection c = new CompositeCollection(); 216 Iterator it = getDataMaps().iterator(); 217 while (it.hasNext()) { 218 DataMap map = (DataMap) it.next(); 219 c.addComposited(map.getProcedures()); 220 } 221 222 return c; 223 } 224 225 public Collection getQueries() { 226 CompositeCollection c = new CompositeCollection(); 227 Iterator it = getDataMaps().iterator(); 228 while (it.hasNext()) { 229 DataMap map = (DataMap) it.next(); 230 c.addComposited(map.getQueries()); 231 } 232 233 return c; 234 } 235 236 public DbEntity getDbEntity(String name) { 237 return _lookupDbEntity(name); 238 } 239 240 public ObjEntity getObjEntity(String name) { 241 return _lookupObjEntity(name); 242 } 243 244 public Procedure getProcedure(String name) { 245 return lookupProcedure(name); 246 } 247 248 public Query getQuery(String name) { 249 return lookupQuery(name); 250 } 251 252 public synchronized void addDataMap(DataMap map) { 253 if (!maps.contains(map)) { 254 maps.add(map); 255 map.setNamespace(this); 256 clearCache(); 257 } 258 } 259 260 265 public synchronized void clearCache() { 266 queryCache.clear(); 267 dbEntityCache.clear(); 268 objEntityCache.clear(); 269 procedureCache.clear(); 270 entityInheritanceCache.clear(); 271 } 272 273 277 protected synchronized void constructCache() { 278 clearCache(); 279 280 Iterator mapIterator = maps.iterator(); 282 while (mapIterator.hasNext()) { 283 DataMap map = (DataMap) mapIterator.next(); 284 285 Iterator objEntities = map.getObjEntities().iterator(); 287 while (objEntities.hasNext()) { 288 ObjEntity oe = (ObjEntity) objEntities.next(); 289 290 objEntityCache.put(oe.getName(), oe); 292 293 String className = oe.getClassName(); 295 if (indexedByClass && className != null) { 296 Class entityClass; 297 try { 298 entityClass = Configuration.getResourceLoader().loadClass( 299 className); 300 } 301 catch (ClassNotFoundException e) { 302 logObj.warn("*** Class '" 305 + className 306 + "' not found in runtime. Ignoring."); 307 continue; 308 } 309 310 if (objEntityCache.get(entityClass) != null) { 311 throw new CayenneRuntimeException(getClass().getName() 312 + ": More than one ObjEntity (" 313 + oe.getName() 314 + " and " 315 + ((ObjEntity) objEntityCache.get(entityClass)).getName() 316 + ") uses the class " 317 + entityClass.getName()); 318 } 319 320 objEntityCache.put(entityClass, oe); 321 if (oe.getDbEntity() != null) { 322 dbEntityCache.put(entityClass, oe.getDbEntity()); 323 } 324 } 325 } 326 327 objEntities = map.getObjEntities().iterator(); 329 while (objEntities.hasNext()) { 330 ObjEntity oe = (ObjEntity) objEntities.next(); 331 332 EntityInheritanceTree node = (EntityInheritanceTree) entityInheritanceCache 335 .get(oe.getName()); 336 if (node == null) { 337 node = new EntityInheritanceTree(oe); 338 entityInheritanceCache.put(oe.getName(), node); 339 } 340 341 String superOEName = oe.getSuperEntityName(); 342 if (superOEName != null) { 343 EntityInheritanceTree superNode = (EntityInheritanceTree) entityInheritanceCache 344 .get(superOEName); 345 346 if (superNode == null) { 347 ObjEntity superOE = (ObjEntity) objEntityCache.get(superOEName); 349 if (superOE != null) { 350 superNode = new EntityInheritanceTree(superOE); 351 entityInheritanceCache.put(superOEName, superNode); 352 } 353 else { 354 logObj.debug("Invalid superEntity '" 356 + superOEName 357 + "' for entity '" 358 + oe.getName() 359 + "'"); 360 continue; 361 } 362 } 363 364 superNode.addChildNode(node); 365 } 366 } 367 368 Iterator dbEntities = map.getDbEntities().iterator(); 370 while (dbEntities.hasNext()) { 371 DbEntity de = (DbEntity) dbEntities.next(); 372 dbEntityCache.put(de.getName(), de); 373 } 374 375 Iterator procedures = map.getProcedures().iterator(); 377 while (procedures.hasNext()) { 378 Procedure proc = (Procedure) procedures.next(); 379 procedureCache.put(proc.getName(), proc); 380 } 381 382 Iterator queries = map.getQueries().iterator(); 384 while (queries.hasNext()) { 385 Query query = (Query) queries.next(); 386 String name = query.getName(); 387 Object existingQuery = queryCache.put(name, query); 388 389 if (existingQuery != null && query != existingQuery) { 390 throw new CayenneRuntimeException("More than one Query for name" 391 + name); 392 } 393 } 394 } 395 } 396 397 400 public synchronized DataMap getDataMap(String mapName) { 401 if (mapName == null) { 402 return null; 403 } 404 405 Iterator it = maps.iterator(); 406 while (it.hasNext()) { 407 DataMap map = (DataMap) it.next(); 408 if (mapName.equals(map.getName())) { 409 return map; 410 } 411 } 412 413 return null; 414 } 415 416 public synchronized void setDataMaps(Collection maps) { 417 this.maps.clear(); 418 this.maps.addAll(maps); 419 clearCache(); 420 } 421 422 425 public Collection getDataMaps() { 426 return mapsRef; 427 } 428 429 432 public synchronized DataMap lookupDataMap(Query q) { 433 if (q.getRoot() instanceof DataMap) { 434 return (DataMap) q.getRoot(); 435 } 436 437 DbEntity entity = lookupDbEntity(q); 438 if (entity != null) { 439 return entity.getDataMap(); 440 } 441 442 Procedure procedure = lookupProcedure(q); 444 return (procedure != null) ? procedure.getDataMap() : null; 445 } 446 447 453 public synchronized DbEntity lookupDbEntity(Class aClass) { 454 if (!indexedByClass) { 455 throw new CayenneRuntimeException("Class index is disabled."); 456 } 457 return this._lookupDbEntity(aClass); 458 } 459 460 466 public synchronized DbEntity lookupDbEntity(DataObject dataObject) { 467 return this._lookupDbEntity(dataObject.getClass()); 468 } 469 470 476 public synchronized DbEntity lookupDbEntity(Query q) { 477 Object root = q.getRoot(); 478 if (root instanceof DbEntity) { 479 return (DbEntity) root; 480 } 481 else if (root instanceof Class ) { 482 return this.lookupDbEntity((Class ) root); 483 } 484 else if (root instanceof ObjEntity) { 485 return ((ObjEntity) root).getDbEntity(); 486 } 487 else if (root instanceof String ) { 488 ObjEntity objEntity = this.lookupObjEntity((String ) root); 489 return (objEntity != null) ? objEntity.getDbEntity() : null; 490 } 491 else if (root instanceof DataObject) { 492 return this.lookupDbEntity((DataObject) root); 493 } 494 return null; 495 } 496 497 502 public EntityInheritanceTree lookupInheritanceTree(ObjEntity entity) { 503 504 EntityInheritanceTree tree = (EntityInheritanceTree) entityInheritanceCache 505 .get(entity.getName()); 506 507 if (tree == null) { 508 511 constructCache(); 514 tree = (EntityInheritanceTree) entityInheritanceCache.get(entity.getName()); 515 } 516 517 return (tree == null || tree.getChildrenCount() == 0) ? null : tree; 519 } 520 521 527 public synchronized ObjEntity lookupObjEntity(Class aClass) { 528 if (!indexedByClass) { 529 throw new CayenneRuntimeException("Class index is disabled."); 530 } 531 532 return this._lookupObjEntity(aClass); 533 } 534 535 541 public synchronized ObjEntity lookupObjEntity(DataObject dataObject) { 542 return this._lookupObjEntity(dataObject.getClass()); 543 } 544 545 555 public synchronized ObjEntity lookupObjEntity(Query q) { 556 557 562 Object root = (q instanceof ProcedureQuery) ? ((ProcedureQuery) q) 563 .getResultClass(Configuration.getResourceLoader()) : q.getRoot(); 564 565 if (root instanceof DbEntity) { 566 throw new CayenneRuntimeException( 567 "Cannot safely resolve the ObjEntity for the query " 568 + q 569 + " because the root of the query is a DbEntity"); 570 } 571 else if (root instanceof ObjEntity) { 572 return (ObjEntity) root; 573 } 574 else if (root instanceof Class ) { 575 return this.lookupObjEntity((Class ) root); 576 } 577 else if (root instanceof String ) { 578 return this.lookupObjEntity((String ) root); 579 } 580 else if (root instanceof DataObject) { 581 return this.lookupObjEntity((DataObject) root); 582 } 583 584 return null; 585 } 586 587 593 public synchronized ObjEntity lookupObjEntity(String entityName) { 594 return this._lookupObjEntity(entityName); 595 } 596 597 public Procedure lookupProcedure(Query q) { 598 Object root = q.getRoot(); 599 if (root instanceof Procedure) { 600 return (Procedure) root; 601 } 602 else if (root instanceof String ) { 603 return this.lookupProcedure((String ) root); 604 } 605 return null; 606 } 607 608 public Procedure lookupProcedure(String procedureName) { 609 610 Procedure result = (Procedure) procedureCache.get(procedureName); 611 if (result == null) { 612 constructCache(); 615 result = (Procedure) procedureCache.get(procedureName); 616 } 617 618 return result; 619 } 620 621 624 public synchronized Query lookupQuery(String name) { 625 Query result = (Query) queryCache.get(name); 626 627 if (result == null) { 628 constructCache(); 631 result = (Query) queryCache.get(name); 632 } 633 return result; 634 } 635 636 public synchronized void removeDataMap(DataMap map) { 637 if (maps.remove(map)) { 638 clearCache(); 639 } 640 } 641 642 public boolean isIndexedByClass() { 643 return indexedByClass; 644 } 645 646 public void setIndexedByClass(boolean b) { 647 indexedByClass = b; 648 } 649 650 659 protected DbEntity _lookupDbEntity(Object object) { 660 if (object instanceof DbEntity) { 661 return (DbEntity) object; 662 } 663 664 DbEntity result = (DbEntity) dbEntityCache.get(object); 665 if (result == null) { 666 constructCache(); 669 result = (DbEntity) dbEntityCache.get(object); 670 } 671 return result; 672 } 673 674 683 protected ObjEntity _lookupObjEntity(Object object) { 684 if (object instanceof ObjEntity) { 685 return (ObjEntity) object; 686 } 687 688 if (object instanceof DataObject) { 689 object = object.getClass(); 690 } 691 692 ObjEntity result = (ObjEntity) objEntityCache.get(object); 693 if (result == null) { 694 constructCache(); 697 result = (ObjEntity) objEntityCache.get(object); 698 } 699 return result; 700 } 701 } | Popular Tags |