1 56 package org.objectstyle.cayenne.access; 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 import java.util.TreeMap ; 66 67 import org.apache.commons.lang.builder.ToStringBuilder; 68 import org.apache.log4j.Logger; 69 import org.objectstyle.cayenne.CayenneRuntimeException; 70 import org.objectstyle.cayenne.ObjectContext; 71 import org.objectstyle.cayenne.access.util.PrimaryKeyHelper; 72 import org.objectstyle.cayenne.graph.GraphChangeHandler; 73 import org.objectstyle.cayenne.map.DataMap; 74 import org.objectstyle.cayenne.map.EntityResolver; 75 import org.objectstyle.cayenne.query.Query; 76 import org.objectstyle.cayenne.query.QueryChain; 77 import org.objectstyle.cayenne.query.QueryExecutionPlan; 78 import org.objectstyle.cayenne.query.QueryRouter; 79 80 92 public class DataDomain implements QueryEngine, PersistenceContext { 93 94 private static Logger logObj = Logger.getLogger(DataDomain.class); 95 96 public static final String SHARED_CACHE_ENABLED_PROPERTY = "cayenne.DataDomain.sharedCache"; 97 public static final boolean SHARED_CACHE_ENABLED_DEFAULT = true; 98 99 public static final String VALIDATING_OBJECTS_ON_COMMIT_PROPERTY = "cayenne.DataDomain.validatingObjectsOnCommit"; 100 public static final boolean VALIDATING_OBJECTS_ON_COMMIT_DEFAULT = true; 101 102 public static final String USING_EXTERNAL_TRANSACTIONS_PROPERTY = "cayenne.DataDomain.usingExternalTransactions"; 103 public static final boolean USING_EXTERNAL_TRANSACTIONS_DEFAULT = false; 104 105 106 protected Map nodes = Collections.synchronizedMap(new TreeMap ()); 107 protected Map nodesByDataMapName = Collections.synchronizedMap(new HashMap ()); 108 protected Collection nodesRef = Collections.unmodifiableCollection(nodes.values()); 109 110 114 protected Map properties = Collections.synchronizedMap(new TreeMap ()); 115 116 protected org.objectstyle.cayenne.map.EntityResolver entityResolver; 117 protected PrimaryKeyHelper primaryKeyHelper; 118 protected DataRowStore sharedSnapshotCache; 119 protected TransactionDelegate transactionDelegate; 120 protected String name; 121 122 protected boolean sharedCacheEnabled; 124 protected boolean validatingObjectsOnCommit; 125 protected boolean usingExternalTransactions; 126 127 130 public DataDomain(String name) { 131 setName(name); 132 resetProperties(); 133 } 134 135 142 public DataDomain(String name, Map properties) { 143 setName(name); 144 initWithProperties(properties); 145 } 146 147 150 protected void resetProperties() { 151 if (properties != null) { 152 properties.clear(); 153 } 154 155 sharedCacheEnabled = SHARED_CACHE_ENABLED_DEFAULT; 156 validatingObjectsOnCommit = VALIDATING_OBJECTS_ON_COMMIT_DEFAULT; 157 usingExternalTransactions = USING_EXTERNAL_TRANSACTIONS_DEFAULT; 158 } 159 160 165 public void initWithProperties(Map properties) { 166 Map localMap = new HashMap (); 168 if (properties != null) { 169 localMap.putAll(properties); 170 } 171 172 this.properties = localMap; 173 174 Object sharedCacheEnabled = localMap.get(SHARED_CACHE_ENABLED_PROPERTY); 175 Object validatingObjectsOnCommit = localMap 176 .get(VALIDATING_OBJECTS_ON_COMMIT_PROPERTY); 177 Object usingExternalTransactions = localMap 178 .get(USING_EXTERNAL_TRANSACTIONS_PROPERTY); 179 180 if (logObj.isDebugEnabled()) { 181 logObj.debug("DataDomain property " 182 + SHARED_CACHE_ENABLED_PROPERTY 183 + " = " 184 + sharedCacheEnabled); 185 logObj.debug("DataDomain property " 186 + VALIDATING_OBJECTS_ON_COMMIT_PROPERTY 187 + " = " 188 + validatingObjectsOnCommit); 189 logObj.debug("DataDomain property " 190 + USING_EXTERNAL_TRANSACTIONS_PROPERTY 191 + " = " 192 + usingExternalTransactions); 193 } 194 195 this.sharedCacheEnabled = (sharedCacheEnabled != null) 197 ? "true".equalsIgnoreCase(sharedCacheEnabled.toString()) 198 : SHARED_CACHE_ENABLED_DEFAULT; 199 this.validatingObjectsOnCommit = (validatingObjectsOnCommit != null) 200 ? "true".equalsIgnoreCase(validatingObjectsOnCommit.toString()) 201 : VALIDATING_OBJECTS_ON_COMMIT_DEFAULT; 202 this.usingExternalTransactions = (usingExternalTransactions != null) 203 ? "true".equalsIgnoreCase(usingExternalTransactions.toString()) 204 : USING_EXTERNAL_TRANSACTIONS_DEFAULT; 205 } 206 207 208 public String getName() { 209 return name; 210 } 211 212 213 public synchronized void setName(String name) { 214 this.name = name; 215 if (sharedSnapshotCache != null) { 216 this.sharedSnapshotCache.setName(name); 217 } 218 } 219 220 225 public boolean isSharedCacheEnabled() { 226 return sharedCacheEnabled; 227 } 228 229 public void setSharedCacheEnabled(boolean sharedCacheEnabled) { 230 this.sharedCacheEnabled = sharedCacheEnabled; 231 } 232 233 239 public boolean isValidatingObjectsOnCommit() { 240 return validatingObjectsOnCommit; 241 } 242 243 249 public void setValidatingObjectsOnCommit(boolean flag) { 250 this.validatingObjectsOnCommit = flag; 251 } 252 253 259 public boolean isUsingExternalTransactions() { 260 return usingExternalTransactions; 261 } 262 263 269 public void setUsingExternalTransactions(boolean flag) { 270 this.usingExternalTransactions = flag; 271 } 272 273 278 public Map getProperties() { 279 return properties; 280 } 281 282 287 public TransactionDelegate getTransactionDelegate() { 288 return transactionDelegate; 289 } 290 291 297 public void setTransactionDelegate(TransactionDelegate transactionDelegate) { 298 this.transactionDelegate = transactionDelegate; 299 } 300 301 305 public synchronized DataRowStore getSharedSnapshotCache() { 306 if (sharedSnapshotCache == null) { 307 this.sharedSnapshotCache = new DataRowStore(name, properties); 308 } 309 310 return sharedSnapshotCache; 311 } 312 313 public synchronized void setSharedSnapshotCache(DataRowStore snapshotCache) { 314 if (this.sharedSnapshotCache != snapshotCache) { 315 if (this.sharedSnapshotCache != null) { 316 this.sharedSnapshotCache.shutdown(); 317 } 318 this.sharedSnapshotCache = snapshotCache; 319 } 320 } 321 322 323 public void addMap(DataMap map) { 324 getEntityResolver().addDataMap(map); 325 } 326 327 328 public DataMap getMap(String mapName) { 329 return getEntityResolver().getDataMap(mapName); 330 } 331 332 336 public synchronized void removeMap(String mapName) { 337 DataMap map = getMap(mapName); 338 if (map == null) { 339 return; 340 } 341 342 Iterator it = nodes.values().iterator(); 344 while (it.hasNext()) { 345 DataNode node = (DataNode) it.next(); 346 node.removeDataMap(mapName); 347 } 348 349 getEntityResolver().removeDataMap(map); 351 352 reindexNodes(); 354 } 355 356 360 public synchronized void removeDataNode(String nodeName) { 361 DataNode removed = (DataNode) nodes.remove(nodeName); 362 if (removed != null) { 363 364 removed.setEntityResolver(null); 365 366 Iterator it = nodesByDataMapName.values().iterator(); 367 while (it.hasNext()) { 368 if (it.next() == removed) { 369 it.remove(); 370 } 371 } 372 } 373 } 374 375 378 public Collection getDataMaps() { 379 return getEntityResolver().getDataMaps(); 380 } 381 382 385 public Collection getDataNodes() { 386 return nodesRef; 387 } 388 389 392 public void reset() { 393 synchronized (nodes) { 394 nodes.clear(); 395 nodesByDataMapName.clear(); 396 397 if (entityResolver != null) { 398 entityResolver.clearCache(); 399 entityResolver = null; 400 } 401 } 402 } 403 404 408 public void clearDataMaps() { 409 getEntityResolver().setDataMaps(Collections.EMPTY_LIST); 410 } 411 412 415 public synchronized void addNode(DataNode node) { 416 417 nodes.put(node.getName(), node); 419 node.setEntityResolver(this.getEntityResolver()); 420 421 Iterator nodeMaps = node.getDataMaps().iterator(); 423 while (nodeMaps.hasNext()) { 424 DataMap map = (DataMap) nodeMaps.next(); 425 this.addMap(map); 426 this.nodesByDataMapName.put(map.getName(), node); 427 } 428 } 429 430 435 public DataContext createDataContext() { 436 return createDataContext(isSharedCacheEnabled()); 437 } 438 439 447 public DataContext createDataContext(boolean useSharedCache) { 448 DataRowStore snapshotCache = (useSharedCache) 451 ? getSharedSnapshotCache() 452 : new DataRowStore(name, properties); 453 454 DataContext context = new DataContext(this, new ObjectStore(snapshotCache)); 455 context.setValidatingObjectsOnCommit(isValidatingObjectsOnCommit()); 456 return context; 457 } 458 459 466 public Transaction createTransaction() { 467 return (isUsingExternalTransactions()) ? Transaction 468 .externalTransaction(getTransactionDelegate()) : Transaction 469 .internalTransaction(getTransactionDelegate()); 470 } 471 472 475 public DataNode getNode(String nodeName) { 476 return (DataNode) nodes.get(nodeName); 477 } 478 479 482 public synchronized void reindexNodes() { 483 nodesByDataMapName.clear(); 484 485 Iterator nodes = this.getDataNodes().iterator(); 486 while (nodes.hasNext()) { 487 DataNode node = (DataNode) nodes.next(); 488 Iterator nodeMaps = node.getDataMaps().iterator(); 489 while (nodeMaps.hasNext()) { 490 DataMap map = (DataMap) nodeMaps.next(); 491 addMap(map); 492 nodesByDataMapName.put(map.getName(), node); 493 } 494 } 495 } 496 497 502 public DataNode lookupDataNode(DataMap map) { 503 synchronized (nodesByDataMapName) { 504 DataNode node = (DataNode) nodesByDataMapName.get(map.getName()); 505 if (node == null) { 506 reindexNodes(); 507 return (DataNode) nodesByDataMapName.get(map.getName()); 508 } 509 else { 510 return node; 511 } 512 } 513 } 514 515 521 public void performQueries( 522 Collection queries, 523 OperationObserver resultConsumer, 524 Transaction transaction) { 525 526 if (queries.isEmpty()) { 527 return; 528 } 529 530 performQuery(new QueryChain(queries), resultConsumer, transaction); 532 } 533 534 538 public void performQueries(Collection queries, OperationObserver observer) { 539 if (queries.isEmpty()) { 540 return; 541 } 542 543 performQuery(new QueryChain(queries), observer); 544 } 545 546 public EntityResolver getEntityResolver() { 547 if (entityResolver == null) { 548 createEntityResolver(); 549 } 550 551 return entityResolver; 552 } 553 554 560 public void setEntityResolver(EntityResolver entityResolver) { 561 this.entityResolver = entityResolver; 562 } 563 564 private synchronized void createEntityResolver() { 566 if (entityResolver == null) { 567 entityResolver = new org.objectstyle.cayenne.map.EntityResolver(); 570 } 571 } 572 573 private void createKeyGenerator() { 575 primaryKeyHelper = new PrimaryKeyHelper(this); 576 } 577 578 581 public synchronized PrimaryKeyHelper getPrimaryKeyHelper() { 582 if (primaryKeyHelper == null) { 585 createKeyGenerator(); 586 } 587 588 return primaryKeyHelper; 589 } 590 591 594 public void shutdown() { 595 this.sharedSnapshotCache.shutdown(); 596 597 Collection dataNodes = getDataNodes(); 598 for (Iterator i = dataNodes.iterator(); i.hasNext();) { 599 DataNode node = (DataNode) i.next(); 600 try { 601 node.shutdown(); 602 } 603 catch (Exception ex) { 604 } 605 } 606 } 607 608 public String toString() { 609 return new ToStringBuilder(this).append("name", name).toString(); 610 } 611 612 615 620 public void commitChangesInContext(ObjectContext context, GraphChangeHandler commitChangeCallback) { 621 new DataDomainCommitAction(this).commit(context, commitChangeCallback); 622 } 623 624 630 public void performQuery(QueryExecutionPlan query, OperationObserver resultConsumer) { 631 632 Transaction transaction = (resultConsumer.isIteratedResult()) ? Transaction 633 .noTransaction() : createTransaction(); 634 635 transaction.performQuery(this, query, resultConsumer); 638 } 639 640 646 public void performQuery( 647 QueryExecutionPlan query, 648 OperationObserver resultConsumer, 649 Transaction transaction) { 650 651 final Map queryMap = new HashMap (); 652 653 655 QueryRouter router = new QueryRouter() { 657 658 public QueryEngine engineForDataMap(DataMap map) { 659 if (map == null) { 660 throw new NullPointerException ( 661 "Null DataMap, can't determine DataNode."); 662 } 663 664 QueryEngine node = lookupDataNode(map); 665 666 if (node == null) { 667 throw new CayenneRuntimeException("No DataNode exists for DataMap " 668 + map); 669 } 670 671 return node; 672 } 673 674 public void useEngineForQuery(QueryEngine engine, Query query) { 675 676 List queriesByEngine = (List ) queryMap.get(engine); 677 if (queriesByEngine == null) { 678 queriesByEngine = new ArrayList (); 679 queryMap.put(engine, queriesByEngine); 680 } 681 682 queriesByEngine.add(query); 683 } 684 }; 685 686 query.route(router, getEntityResolver()); 687 688 Iterator nodeIt = queryMap.entrySet().iterator(); 690 while (nodeIt.hasNext()) { 691 Map.Entry entry = (Map.Entry ) nodeIt.next(); 692 QueryEngine nextNode = (QueryEngine) entry.getKey(); 693 Collection nodeQueries = (Collection ) entry.getValue(); 694 695 nextNode.performQueries(nodeQueries, resultConsumer, transaction); 696 } 697 } 698 } | Popular Tags |