[hibernate-commits] Hibernate SVN: r11294 - in trunk/HibernateExt: shards and 56 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Sat Mar 17 12:31:43 EDT 2007


Author: max.ross
Date: 2007-03-17 12:31:42 -0400 (Sat, 17 Mar 2007)
New Revision: 11294

Added:
   trunk/HibernateExt/shards/
   trunk/HibernateExt/shards/build.properties.dist
   trunk/HibernateExt/shards/build.xml
   trunk/HibernateExt/shards/changelog.txt
   trunk/HibernateExt/shards/doc/
   trunk/HibernateExt/shards/doc/api/
   trunk/HibernateExt/shards/doc/api/package.html
   trunk/HibernateExt/shards/doc/reference/
   trunk/HibernateExt/shards/doc/reference/.cvsignore
   trunk/HibernateExt/shards/doc/reference/build.xml
   trunk/HibernateExt/shards/doc/reference/en/
   trunk/HibernateExt/shards/doc/reference/en/images/
   trunk/HibernateExt/shards/doc/reference/en/images/hibernate_logo_a.png
   trunk/HibernateExt/shards/doc/reference/en/master.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/
   trunk/HibernateExt/shards/doc/reference/en/modules/architecture.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/configuration.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/limitations.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/querying.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/resharding.xml
   trunk/HibernateExt/shards/doc/reference/en/modules/shardstrategy.xml
   trunk/HibernateExt/shards/doc/reference/en/styles/
   trunk/HibernateExt/shards/doc/reference/en/styles/fopdf.xsl
   trunk/HibernateExt/shards/doc/reference/en/styles/html.css
   trunk/HibernateExt/shards/doc/reference/en/styles/html.xsl
   trunk/HibernateExt/shards/doc/reference/en/styles/html_chunk.xsl
   trunk/HibernateExt/shards/etc/
   trunk/HibernateExt/shards/etc/hibernate.properties
   trunk/HibernateExt/shards/etc/log4j.properties
   trunk/HibernateExt/shards/jdbc/
   trunk/HibernateExt/shards/jdbc/hsqldb.jar
   trunk/HibernateExt/shards/jdbc/mysql-3.0.14.jar
   trunk/HibernateExt/shards/lgpl.txt
   trunk/HibernateExt/shards/lib/
   trunk/HibernateExt/shards/lib/README.txt
   trunk/HibernateExt/shards/readme.txt
   trunk/HibernateExt/shards/src/
   trunk/HibernateExt/shards/src/java/
   trunk/HibernateExt/shards/src/java/org/
   trunk/HibernateExt/shards/src/java/org/hibernate/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/BaseHasShardIdList.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/CrossShardAssociationException.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/HasShardIdList.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/Shard.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardId.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedConfiguration.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedTransaction.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/cfg/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/cfg/ShardedEnvironment.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddCriterionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddOrderEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateAliasEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateSubcriteriaEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaId.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheRegionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheableEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCommentEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchSizeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFirstResultEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFlushModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetLockModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetMaxResultsEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetProjectionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetResultTransformerEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetTimeoutEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteria.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteria.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteriaImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionFactoryImplementor.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionImplementor.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/GeneratorRequiringControlSessionProvider.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardEncodingIdentifierGenerator.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedTableHiLoGenerator.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedUUIDGenerator.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/BaseShardLoadBalancer.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RandomShardLoadBalancer.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancer.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/ShardLoadBalancer.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/package-info.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/AdHocQueryFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ExitOperationsQueryCollector.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/NamedQueryFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryId.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryResult.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigDecimalEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigIntegerEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBinaryEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBooleanEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetByteEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheRegionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheableEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarDateEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCharacterEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCommentEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDateEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDoubleEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetEntityEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFetchSizeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFirstResultEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFloatEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFlushModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetIntegerEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLocaleEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLockModeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLongEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetMaxResultsEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterListEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParametersEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetPropertiesEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetReadOnlyEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetResultTransformerEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetSerializableEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetShortEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetStringEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTextEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeoutEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimestampEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQuery.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQueryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/BaseStatefulInterceptorFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ControlSessionProvider.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecorator.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/DisableFilterOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/EnableFilterOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/OpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/RequiresSession.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetCacheModeOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetFlushModeOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetReadOnlyOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetSessionOnRequiresSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetupTransactionOpenSessionEvent.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardIdResolver.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSession.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionException.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/StatefulInterceptorFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SubsetShardedSessionFactoryImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/LoadBalancedSequentialShardAccessStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardAccessStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardOperationCallable.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/SequentialShardAccessStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ShardAccessStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/StartAwareFutureTask.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ConcatenateListsExitStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/CountExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/DistinctExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationsCollector.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstNonNullResultExitStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstResultExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/MaxResultsExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/RowCountExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/AllShardsShardResolutionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/BaseShardResolutionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/ShardResolutionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/BaseShardSelectionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/RoundRobinShardSelectionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyData.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyDataImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardSelectionStrategy.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/transaction/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/transaction/ShardedTransactionImpl.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/InterceptorDecorator.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Iterables.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Lists.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Maps.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Pair.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Preconditions.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Sets.java
   trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/StringUtil.java
   trunk/HibernateExt/shards/src/test/
   trunk/HibernateExt/shards/src/test/org/
   trunk/HibernateExt/shards/src/test/org/hibernate/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllFastTests.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllTests.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/BaseHasShardIdListTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/InstanceShardStrategyImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardOperationDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedConfigurationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedSessionFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedTransactionDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddCriterionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddOrderEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateAliasEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateSubcriteriaEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaEventDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheRegionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheableEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCommentEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchSizeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFirstResultEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFlushModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetLockModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetMaxResultsEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetProjectionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetResultTransformerEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetTimeoutEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedCriteriaDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedSubcriteriaImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/ClassMetadataDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/CriteriaDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/EntityPersisterDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/InterceptorDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/QueryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionImplementorDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/TypeDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/engine/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/engine/ShardedSessionImplementorDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedTableHiLoGeneratorTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedUUIDGeneratorTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/UUIDBigIntGenerator.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCasePermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ConfigPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/HasPermutation.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/IdGenType.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/MemoryLeakPlugger.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/Permutation.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/PermutedIntegrationTests.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ShardAccessStrategyType.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/id/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/id/IdGeneratorPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/InterceptorBehaviorPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/MemoryLeakTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelQueryPermutedIntegrationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/package-info.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/BaseDatabasePlatform.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatform.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatformFactory.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard0.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard1.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard2.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/MySQLDatabasePlatform.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard0.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard1.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard2.hibernate.cfg.xml
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancerTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/ShardLoadBalancerDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Building.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Elevator.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Escalator.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Floor.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Office.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Person.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Tenant.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Window.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryEventDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigDecimalEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigIntegerEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBinaryEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBooleanEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetByteEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheRegionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheableEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarDateEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCharacterEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCommentEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDateEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDoubleEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetEntityEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFetchSizeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFirstResultEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFloatEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFlushModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetIntegerEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLocaleEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLockModeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLongEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetMaxResultsEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterListEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParametersEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetPropertiesEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetReadOnlyEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetResultTransformerEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetSerializableEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetShortEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetStringEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTextEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeoutEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimestampEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/ShardedQueryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecoratorTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/DisableFilterOpenSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/EnableFilterOpenSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/OpenSessionEventDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetCacheModeOpenSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetFlushModeOpenSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetReadOnlyOpenSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetSessionOnRequiresSessionEventTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardIdResolverDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionFactoryImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyFactoryDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardAccessStrategyTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardOperationCallableTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ShardAccessStrategyDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/StartAwareFutureTaskTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitOperationUtilsTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitStrategyDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/MaxResultExitOperationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactoryTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/RowCountExitOperationTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDataDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategyTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/ShardSelectionStrategyDefaultMock.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/transaction/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/transaction/ShardedTransactionImplTest.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcStrategy.java
   trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcUtil.java
Log:
initial shards check-in

Added: trunk/HibernateExt/shards/build.properties.dist
===================================================================
--- trunk/HibernateExt/shards/build.properties.dist	                        (rev 0)
+++ trunk/HibernateExt/shards/build.properties.dist	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,4 @@
+common.dir=.
+src.dir=src
+test.dir=test
+hibernate-core.home=../hibernate-3.2
\ No newline at end of file

Added: trunk/HibernateExt/shards/build.xml
===================================================================
--- trunk/HibernateExt/shards/build.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/build.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,89 @@
+<!--
+
+  Hibernate Annotations ANT build script.
+
+  You need JDK 5.0 installed to build Hibernate Annotations.
+
+-->
+
+<project name="Hibernate Search" default="dist" basedir=".">
+
+    <!-- Give user a chance to override without editing this file
+               (and without typing -D each time it compiles it) -->
+    <property file="build.properties"/>
+    <property file="${user.home}/.ant.properties"/>
+
+    <!-- Name of project and version, used to create filenames -->
+    <property name="Name" value="Hibernate Shards"/>
+    <property name="name" value="hibernate-shards"/>
+    <property name="version" value="3.0.0.BETA1"/>
+    <property name="javadoc.packagenames" value="org.hibernate.shards.*"/>
+    <property name="copy.test" value="true"/>
+    <property name="javac.source" value="1.5"/>
+    <property name="javac.target" value="1.5"/>
+    <property name="jdbc.dir" value="jdbc"/>
+    <property name="common.dir" value="${basedir}/../common"/>
+
+    <import file="${common.dir}/common-build.xml"/>
+
+    <!-- test set customization to support permuted tests -->
+    <fileset dir="${testclasses.dir}" id="junit.batchtestset">
+        <include name="**/*Test.class"/>
+        <include name="**/PermutedIntegrationTests.class"/>
+	<exclude name="**/*PermutedTest.class"/>
+    </fileset>
+
+    <!-- unit test class path customization -->
+    <path id="junit.moduleclasspath">
+        <pathelement location="etc"/>
+        <fileset dir="${jdbc.dir}">
+            <include name="*.jar"/>
+            <include name="*.zip"/>
+        </fileset>
+    </path>
+
+    <!-- override any needed target that need customization
+         typical usage: override compile and refers to common-build.compile to delegate to the common target -->
+
+    <target name="jar" depends="compile" description="Build the distribution .jar file">
+        <!-- probably make sense to move that up -->
+        <mkdir dir="${classes.dir}/META-INF"/>
+        <manifest file="${classes.dir}/META-INF/MANIFEST.MF">
+            <attribute name="Product" value="${Name}"/>
+            <attribute name="Version" value="${version}"/>
+        </manifest>
+        <antcall target="common-build.jar"/>
+    </target>
+
+    <target name="compiletest" depends="common-build.compiletest">
+        <copy todir="${testclasses.dir}">
+            <fileset dir="src/test">
+                <exclude name="**/*.java"/>
+            </fileset>
+        </copy>
+    </target>
+
+    <!-- Some of this can probably be moved to common-build... -->
+	<target name="dist" depends="jar,javadoc,copysource,copytest,copylib,extras"
+			description="Build everything">
+
+		<ant inheritall="false" dir="${basedir}/doc/reference"/>
+		<copy todir="${dist.dir}/doc/reference" failonerror="false">
+			<fileset dir="${basedir}/doc/reference/build">
+				<include name="**/*.*"/>
+			</fileset>
+		</copy>
+
+		<copy todir="${dist.dir}" failonerror="false">
+			<fileset dir="${common.dir}">
+				<include name="common-build.xml"/>
+			</fileset>
+		</copy>
+
+        <copy file="${basedir}/build.properties.dist" tofile="${dist.dir}/build.properties" failonerror="false">
+		</copy>
+		<antcall target="common-build.dist"/>
+	</target>
+
+
+</project>

Added: trunk/HibernateExt/shards/changelog.txt
===================================================================
--- trunk/HibernateExt/shards/changelog.txt	                        (rev 0)
+++ trunk/HibernateExt/shards/changelog.txt	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,7 @@
+Hibernate Shards Changelog
+==========================
+
+3.0.0.BETA1 (20-03-2007)
+---------------------
+
+Initial release
\ No newline at end of file

Added: trunk/HibernateExt/shards/doc/api/package.html
===================================================================
--- trunk/HibernateExt/shards/doc/api/package.html	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/api/package.html	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1 @@
+<body></body>

Added: trunk/HibernateExt/shards/doc/reference/.cvsignore
===================================================================
--- trunk/HibernateExt/shards/doc/reference/.cvsignore	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/.cvsignore	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1 @@
+build

Added: trunk/HibernateExt/shards/doc/reference/build.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/build.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/build.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,17 @@
+<project name="Documentation" default="all.doc" basedir=".">
+
+    <!-- Use the core Hibernate3 doc build system -->
+    <import file="../../../common/common-build.xml"/>
+    <import file="${hibernate-cvs.doc.reference}/build.xml"/>
+
+
+    <target name="all.doc" depends="clean">
+
+        <!-- TRANSLATOR: Duplicate this call for your language -->
+        <antcall target="lang.all">
+            <param name="docname" value="hibernate_shard"/>
+            <param name="lang" value="en"/>
+        </antcall>
+    </target>
+
+</project>

Added: trunk/HibernateExt/shards/doc/reference/en/images/hibernate_logo_a.png
===================================================================
(Binary files differ)


Property changes on: trunk/HibernateExt/shards/doc/reference/en/images/hibernate_logo_a.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/HibernateExt/shards/doc/reference/en/master.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/master.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/master.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
+        "../../../../../Hibernate3/doc/reference/support/docbook-dtd/docbookx.dtd" [
+        <!ENTITY architecture SYSTEM "modules/architecture.xml">
+        <!ENTITY configuration SYSTEM "modules/configuration.xml">
+        <!ENTITY shardstrategy SYSTEM "modules/shardstrategy.xml">
+        <!ENTITY resharding SYSTEM "modules/resharding.xml">
+        <!ENTITY querying SYSTEM "modules/querying.xml">
+        <!ENTITY limitations SYSTEM "modules/limitations.xml">
+        ]>
+<book lang="en">
+    <bookinfo>
+        <title>Hibernate Shards</title>
+        <subtitle>Horizontal Partitioning With Hibernate</subtitle>
+        <subtitle>Reference Guide</subtitle>
+        <releaseinfo>3.0.0.BETA1</releaseinfo>
+        <mediaobject>
+            <imageobject>
+                <imagedata fileref="images/hibernate_logo_a.png" format="PNG"/>
+            </imageobject>
+        </mediaobject>
+    </bookinfo>
+    <toc/>
+    <preface id="preface">
+        <title>Preface</title>
+        <para>
+            You can't always put all your relational data in a single relational database.
+            Sometimes you simply have too much data. Sometimes you have a distributed deployment architecture
+            (network latency between California and India might be too high to have a single database). There might
+            even be non-technical reasons (a potential customer simply won't do the deal unless her company's data lives in its
+            own db instance). Whatever your reasons, talking to multiple relational databases inevitably complicates
+            the development of your application. Hibernate Shards is a framework that is designed to encapsulate and
+            minimize this complexity by adding support for
+            <ulink url="http://en.wikipedia.org/w/index.php?title=Partition_%28database%29&amp;oldid=99996308">
+                horizontal partitioning
+            </ulink>
+            on top of Hibernate Core. Simply put, we aim to provide a unified view of multiple databases via Hibernate.
+        </para>
+        <para>
+            So what's a shard? Good question. "Shard" is just another word for "segment" or "partition," but
+            it's the term of choice within Google. Hibernate Shards was originally the
+            <ulink url="http://www.google.com/support/jobs/bin/static.py?page=about.html">20 percent project</ulink>
+            of a small team of Google engineers, so the project nomenclature revolved around shards from the beginning.
+            We're open sourcing what we have so far because we want the Hibernate
+            community to be able to benefit from our efforts as soon as possible, but also with the hope and expectation
+            that this community will be able to help us reach a GA release much faster than if we kept this
+            under wraps. We fully expect to find glitches in both our design and implementation, and we appreciate your
+            patience as we work through them.
+        </para>
+    </preface>
+
+    &architecture;
+
+    &configuration;
+
+    &shardstrategy;
+
+    &resharding;
+
+    &querying;
+
+    &limitations;
+</book>

Added: trunk/HibernateExt/shards/doc/reference/en/modules/architecture.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/architecture.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/architecture.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="shards-architecture">
+    <title>Architecture</title>
+    <sect1 id="shards-architecture-overview" revision="1">
+        <title>Overview</title>
+        <para>
+            Hibernate Shards is an extension to Hibernate Core that is designed to encapsulate and minimize the
+            complexity of working with sharded (horizontally partitioned) data. Hibernate Shards can be conceptually
+            divided into two areas, both of which you will need to understand in order to be successful. The two areas
+            are:
+            <itemizedlist mark="opencircle">
+                <listitem>
+                    <para>Generalized sharding logic</para>
+                </listitem>
+                <listitem>
+                    <para>Application specific sharding logic</para>
+                </listitem>
+            </itemizedlist>
+            We'll discuss each of these areas in turn.
+        </para>
+    </sect1>
+    <sect1 id="shards-architecture-general" revision="1">
+        <title>Generalized Sharding Logic</title>
+        <para>The primary goal of Hibernate Shards is to enable application developers to query and transact against
+            sharded datasets using the standard Hibernate Core API. This allows existing applications that use Hibernate
+            but do not yet need sharding to adopt our solution without major refactoring if and when they do reach this
+            stage. This also allows application developers who are familiar with Hibernate, need sharding, and are starting from
+            scratch to become productive in a short amount of time because there will be no need to ramp-up on a new
+            toolset. With this goal in mind, it should come as no surprise that Hibernate Shards primarily consists of
+            shard-aware implementations of many of the Hibernate Core interfaces you already know and love.
+        </para>
+        <para>
+            Most Hibernate-related application code primarily interacts with four interfaces provided by Hibernate
+            Core:
+            <itemizedlist mark="opencircle">
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.Session</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.SessionFactory</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.Criteria</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.Query</classname>
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </para>
+        <para>
+            Hibernate Shards provides shard-aware extensions of these four interfaces so that your code does not need to
+            know that it is interacting with a sharded dataset (unless of course you have specific reasons for exposing
+            this fact). The shard-aware extensions are:
+            <itemizedlist mark="opencircle">
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.session.ShardedSession</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.ShardedSessionFactory</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.criteria.ShardedCriteria</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.query.ShardedQuery</classname>
+                    </para>
+                </listitem>
+            </itemizedlist>
+            The implementations we provide for these four shard-aware interfaces serve as a sharding engine that knows how to apply your
+            application-specific sharding logic across your various data stores. We don't expect application developers
+            to need to write much code that knowingly interacts with these interfaces, so if you do find yourself
+            declaring or passing around Sharded instances take a step back and see if you can make do with the parent
+            interface instead.
+        </para>
+    </sect1>
+    <sect1 id="shards-architecture-application" revision="1">
+        <title>Application Specific Sharding Logic</title>
+        <para>
+            Every application that uses Hibernate Shards will have its own rules for how data gets distributed across
+            its shards. Rather than attempt to anticipate all these rules (an effort practically guaranteed to fail) we
+            have instead provided a set of interfaces behind which you can encode your application's data distribution
+            logic. These interfaces are:
+            <itemizedlist mark="opencircle">
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.strategy.selection.ShardSelectionStrategy</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.strategy.resolution.ShardResolutionStrategy</classname>
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <classname>org.hibernate.shards.strategy.access.ShardAccessStrategy</classname>
+                    </para>
+                </listitem>
+            </itemizedlist>
+            The implementations you provide for these three interfaces plus the id generation implementation you choose
+            (more on this in the Sharding Strategy chapter) comprise the
+            <emphasis>Sharding Strategy</emphasis>
+            for your application. The sharding engine described in the previous section knows how to use the Sharding
+            Strategy you provide.
+        </para>
+        <para>In order to help you get up and running quickly, Hibernate Shards comes with a couple simple
+            implementations of these interfaces. We expect that they will aid you in your prototyping or in the early
+            stages of actual application development, but we also expect that, sooner or later, most applications will
+            provide their own implementations.
+        </para>
+        <para>For more information on Sharding Strategies please consult the chapter of the same name.</para>
+    </sect1>
+</chapter>


Property changes on: trunk/HibernateExt/shards/doc/reference/en/modules/architecture.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/HibernateExt/shards/doc/reference/en/modules/configuration.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/configuration.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/configuration.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="shards-configuration">
+    <title>Configuration</title>
+    <sect1 id="shards-configuration-overview" revision="1">
+        <title>Overview</title>
+        <para>
+            When using Hibernate Shards you will find yourself making typical Hibernate Core API calls most of them
+            time. However, in order to get your shard-aware datasource properly configured you'll need to understand a
+            few concepts that are specific to Hibernate Shards. We'll introduce these new concepts as part of a concrete
+            example.  Let's take a look at the object model, database schema, and mapping we'll be using in our
+            examples throughout the documentation.
+        </para>
+        <para>
+            Our example application will receive weather reports from cities all over the world and store this information in a
+            relational database.
+        </para>
+        <sect2 id="shards-configuration-overview-sample-schema" revision="1">
+            <title>Weather Report Database Schema</title>
+            <programlisting><![CDATA[
+CREATE TABLE WEATHER_REPORT (
+    REPORT_ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+    CONTINENT ENUM('AFRICA', 'ANTARCTICA', 'ASIA', 'AUSTRALIA', 'EUROPE', 'NORTH AMERICA', 'SOUTH AMERICA'),
+    LATITUDE FLOAT,
+    LONGITUDE FLOAT,
+    TEMPERATURE INT,
+    REPORT_TIME TIMESTAMP
+);
+                ]]></programlisting>
+        </sect2>
+        <sect2 id="shards-configuration-overview-sample-model" revision="1">
+            <title>Weather Report Object Model</title>
+            <programlisting><![CDATA[
+public class WeatherReport {
+    private Integer reportId;
+    private String continent;
+    private BigDecimal latitude;
+    private BigDecimal longitude;
+    private int temperature;
+    private Date reportTime;
+
+    ... // getters and setters
+}
+                ]]></programlisting>
+        </sect2>
+        <sect2 id="shards-configuration-overview-sample-mapping" revision="1">
+            <title>Contents of weather.hbm.xml</title>
+            <programlisting><![CDATA[
+<hibernate-mapping package="org.hibernate.shards.example.model">
+    <class name="WeatherReport" table="WEATHER_REPORT">
+        <id name="reportId" column="REPORT_ID">
+            <generator class="native"/>
+        </id>
+        <property name="continent" column="CONTINENT"/>
+        <property name="latitude" column="LATITUDE"/>
+        <property name="longitude" column="LONGITUDE"/>
+        <property name="temperature" column="TEMPERATURE"/>
+        <property name="reportTime" type="timestamp" column="REPORT_TIME"/>
+    </class>
+</hibernate-mapping>
+                ]]></programlisting>
+        </sect2>
+    </sect1>
+    <sect1 id="shards-configuration-sf" revision="1">
+        <title>Obtaining a ShardedSessionFactory</title>
+        <para>
+            Before we show you how to obtain a
+            <classname>ShardedSessionFactory</classname>
+            let's look at some code that allows you to obtain a standard
+            <classname>SessionFactory</classname>.
+            <programlisting><![CDATA[
+1    public SessionFactory createSessionFactory() {
+2        Configuration config = new Configuration();
+3        config.configure("weather.hibernate.cfg.xml");
+4        config.addResource("weather.hbm.xml");
+5        return config.buildSessionFactory();
+6    }
+]]></programlisting>
+            This is pretty straightforward. We're instantiating a new
+            <classname>Configuration</classname>
+            object (line 2), telling that
+            <classname>Configuration</classname>
+            to read
+            its properties from a resource named "weather.hibernate.cfg.xml" (line 3), and then providing
+            "weather.hbm.xml" as a source of OR
+            mapping data (line 4). We are then asking the
+            <classname>Configuration</classname>
+            to build a
+            <classname>SessionFactory</classname>, which we return (line 5).
+        </para>
+        <para>
+            Let's also take a look at the configuration file we're loading in:
+            <programlisting><![CDATA[
+ 1    <!-- Contents of weather.hibernate.cfg.xml -->
+ 2    <hibernate-configuration>
+ 3      <session-factory name="HibernateSessionFactory">
+ 4        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+ 5        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+ 6        <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
+ 7        <property name="connection.username">my_user</property>
+ 8        <property name="connection.password">my_password</property>
+ 9      </session-factory>
+ 10   </hibernate-configuration>
+                ]]></programlisting>
+        </para>
+        <para>
+            As you can see, there's nothing particularly interesting going on in the configuration file or the mapping
+            file.
+        </para>
+        <para>
+            You'll be pleased to know that the process of configuring your application to use Hibernate Shards is not
+            radically
+            different. The main difference is that we're providing connectivity information for multiple datasources,
+            and we're
+            also describing our desired sharding behavior via a
+            <classname>ShardStrategyFactory</classname>. Let's look at some sample configuration code for our weather
+            report application, which we're going to run with 3 shards.
+            <programlisting><![CDATA[
+1     public SessionFactory createSessionFactory() {
+2         Configuration prototypeConfig = new Configuration().configure("shard0.hibernate.cfg.xml");
+3         prototypeConfig.addResource("weather.hbm.xml");
+4         List<Configuration> shardConfigs = new ArrayList<Configuration>();
+5         shardConfigs.add(new Configuration().configure("shard0.hibernate.cfg.xml");
+6         shardConfigs.add(new Configuration().configure("shard1.hibernate.cfg.xml");
+7         shardConfigs.add(new Configuration().configure("shard2.hibernate.cfg.xml");
+8         ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
+9         ShardedConfiguration shardedConfig = new ShardedConfiguration(
+10            prototypeConfig,
+11            shardConfigs,
+12            shardStrategyFactory);
+13        return shardedConfig.buildShardedSessionFactory();
+14    }
+15
+16    ShardStrategyFactory buildShardStrategyFactory() {
+17        ShardStrategyFactory shardStrategyFactory = new StrategyFactory() {
+18            public ShardStrategy newShardStrategy(List shardIds) {
+19                RoundRobinShardLoadBalancer loadBalancer = new RoundRobinShardLoadBalancer(shardIds);
+20                ShardSelectionStrategy pss = new RoundRobinShardSelectionStrategy(loadBalancer);
+21                ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(shardIds);
+22                ShardAccessStrategy pas = new SequentialShardAccessStrategy();
+23                return new ShardStrategyImpl(pss, prs, pas);
+24            }
+25        }
+26        return shardStrategyFactory;
+27    }
+  ]]></programlisting>
+        </para>
+        <para>
+            So what's going on here? First, you'll notice that we're actually allocating four
+            <classname>Configurations</classname>. The first <classname>Configuration</classname>
+            we allocate (line 2) is the prototype <classname>Configuration</classname>. The
+            <classname>ShardedSessionFactory</classname>
+            we eventually construct (line 13) will contain references to 3 standard
+            <classname>SessionFactory</classname> objects. Each of these 3 standard
+            <classname>SessionFactory</classname> objects will have been constructed from the prototype configuration. The
+            only attributes that will differ across these standard <classname>SessionFactory</classname>
+            objects are:
+            <itemizedlist mark="opencircle">
+                <listitem>
+                    <para>connection.url</para>
+                </listitem>
+                <listitem>
+                    <para>connection.user</para>
+                </listitem>
+                <listitem>
+                    <para>connection.password</para>
+                </listitem>
+            </itemizedlist>
+            The three <classname>Configuration</classname> objects we're loading (lines 5 - 7) will be consulted for the
+            shard-specific database url, database user, and database password, and that's all. This means that if you change the
+            connection pool parameters in shard1.hibernate.cfg.xml, those parameters will be ignored. If you add another
+            mapping file to the <classname>Configuration</classname>
+            loaded with the properties defined in weather2.hibernate.cfg.xml, that mapping will be ignored.
+            With the exception of the properties listed above, the configuration of our shard-aware
+            <classname>SessionFactory</classname> comes entirely from the prototype
+            <classname>Configuration</classname>. This may seem a bit strict, but the sharding code
+            needs to assume that all shards are identically configured.
+        </para>
+        <para>
+            If you're looking at this code and thinking it seems a bit silly to provide fully-formed configuration
+            documents that, save a couple special properties, are ignored, rest assured we've looked at this code and
+            thought the same thing. We expect the configuration mechanism to evolve over time. We picked this particular
+            mechanism because it allowed the greatest reuse of configuration code that was already available in
+            Hibernate Core.
+        </para>
+        <para>
+            Once we've built our <classname>Configuration</classname>
+            objects we need to put together a <classname>ShardStrategyFactory</classname>
+            (line 8). A <classname>ShardStrategyFactory</classname>
+            is an object that knows how to create the 3 types of strategies that programmers can use to control the sharding
+            behavior of the system. For more information on these strategies please see the chapters titled Sharding Strategies.
+        </para>
+        <para>
+            Once we've instantiated our <classname>ShardStrategyFactory</classname> we can construct a
+            <classname>ShardedConfiguration</classname> (line 9), and once we've constructed
+            our <classname>ShardedConfiguration</classname> we can ask it to create a
+            <classname>ShardedSessionFactory</classname> (line 13). It's important to note that
+            <classname>ShardedSessionFactory</classname> extends <classname>SessionFactory</classname>. This means we can return a standard
+            <classname>SessionFactory</classname> (line 1). Our application's Hibernate code doesn't need
+            to know that it's interacting with sharded data.
+        </para>
+        <para>
+            Now let's take a look at the configuration and mapping files that we loaded in. You'll definitely recognize
+            them, but there are a few key additions and modifications related to sharding.
+            <programlisting><![CDATA[
+ 1    <!-- Contents of weather0.hibernate.cfg.xml -->
+ 2    <hibernate-configuration>
+ 3      <session-factory name="HibernateSessionFactory0"> <!-- note the different name -->
+ 4        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+ 5        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+ 6        <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
+ 7        <property name="connection.username">my_user</property>
+ 8        <property name="connection.password">my_password</property>
+ 9        <property name="hibernate.connection.shard_id">0</property> <!-- new -->
+ 10      <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property> <!-- new -->
+ 11    </session-factory>
+ 12  </hibernate-configuration>
+                ]]></programlisting>
+            <programlisting><![CDATA[
+ 1    <!-- Contents of weather1.hibernate.cfg.xml -->
+ 2    <hibernate-configuration>
+ 3      <session-factory name="HibernateSessionFactory1"> <!-- note the different name -->
+ 4        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+ 5        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+ 6        <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
+ 7        <property name="connection.username">my_user</property>
+ 8        <property name="connection.password">my_password</property>
+ 9        <property name="hibernate.connection.shard_id">1</property> <!-- new -->
+ 10      <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property> <!-- new -->
+ 11    </session-factory>
+ 12  </hibernate-configuration>
+                ]]></programlisting>
+            We'll skip the contents of weather2.hibernate.cfg.xml because the pattern should by now be obvious. We're
+            giving each session factory a unique name via the name attribute of the session-factory element, and we're
+            also giving each session factory a shard id. This is required. If you try to configure a
+            <classname>ShardedSessionFactory</classname> with a <classname>Configuration</classname>
+            object that does not have a shard id you'll get an error. At the moment we require that the shard id of one
+            of your session factories be 0. Beyond that, the internal representation of a shard id is a
+            <classname>java.lang.Integer</classname> so all values within that range are legal. Finally, each shard that is mapped into a
+            <classname>ShardedSessionFactory</classname> must have a unique shard id. If you have a duplicate shard id you'll get an error.
+        </para>
+        <para>
+            The other noteworthy addition is the rather verbose but hopefully descriptive
+            "hibernate.shard.check_all_associated_objects_for_different_shards." You can read more about this in the
+            chapter on limitations.
+        </para>
+        <para>
+            Now let's still see how the mapping file has changed.
+            <programlisting><![CDATA[
+<hibernate-mapping package="org.hibernate.shards.example.model">
+    <class name="WeatherReport" table="WEATHER_REPORT">
+        <id name="reportId" column="REPORT_ID" type="long">
+            <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+        </id>
+        <property name="country" column="COUNTRY"/>
+        <property name="city" column="CITY"/>
+        <property name="temperature" column="TEMPERATURE"/>
+        <property name="reportTime" type="timestamp" column="REPORT_TIME"/>
+    </class>
+</hibernate-mapping>
+                ]]></programlisting>
+            The only meaningful change in the mapping file from the non-sharded version is in our selection of a
+            shard-aware id generator. We'll cover id generation in more detail in the chapter on Shard Strategies.
+        </para>
+    </sect1>
+    <sect1 id="shards-configuration-limitations" revision="1">
+        <title>Configuration Limitations</title>
+        <para>
+            Many of you will quickly realize that the configuration mechanism we've provided won't work if you're
+            configuring your <classname>SessionFactory</classname>
+            via JPA or Hibernate Annotations. It's true. We expect these deficiencies to be addressed shortly.
+        </para>
+    </sect1>
+</chapter>


Property changes on: trunk/HibernateExt/shards/doc/reference/en/modules/configuration.xml
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/HibernateExt/shards/doc/reference/en/modules/limitations.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/limitations.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/limitations.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="shards-limitations">
+    <title>Limitations</title>
+    <sect1 id="shards-limitations-api" revision="1">
+        <title>Incomplete Implementation of Hibernate API</title>
+        <para>
+            In order to speed-up the initial release of Hibernate Shards, some
+            parts of the Hibernate API that we rarely use were left unimplemented. Of course things that
+            we rarely used are probably critical for some applications, so if we've left you out in the cold
+            we apologize. We're committed to getting the rest of the api implemented quickly. For details on which
+            methods were not implemented, please see the Javadoc for <classname>ShardedSessionImpl</classname>,
+            <classname>ShardedCriteriaImpl</classname>, and <classname>ShardedQueryImpl</classname>.
+        </para>
+    </sect1>
+    <sect1 id="shards-limitations-cross-shard" revision="1">
+        <title>Cross-Shard Object Graphs</title>
+        <para>
+            Hibernate Shards does not currently support cross-shard object graphs.
+        </para>
+        <para>
+            In other words, it is illegal to create an association between objects A and B when A and B
+            live on different shards. The workaround is to define a property on A which uniquely identifies an
+            object of type B, and to use that property to load object B (remember what life was like
+            before Hibernate? Yeah, just like that.)
+        </para>
+        <para>
+            For example:
+            <programlisting>
+                --need domain for examples--
+            </programlisting>
+        </para>
+        <para>
+            In some applications your model may be constructed in such a way that it is difficult to make this kind
+            of mistake, but in some applications it may be easier. The scary thing here is that if you make this
+            mistake, Hibernate will consider the "bad" object in the list to be a new object and, assuming you have
+            cascades enabled for this relationship, it will create a new version of this object on a different shard.
+            This is trouble. In order to help prevent this sort of thing from happening we have an interceptor
+            called <classname>CrossShardRelationshipDetectingInterceptor</classname> that checks for cross-shard
+            relationships on every object that is created or saved.
+        </para>
+        <para>
+            Unfortunately there is a cost associated with using the <classname>CrossShardRelationshipDetectingInterceptor</classname>.
+            In order to determine the shard on which an associated object resides we need to fetch the object from the
+            database, so if you have lazy-loaded associations the interceptor will resolve those associations as part
+            of its checks.  This is potentially quite expensive, and may not be suitable for a production system.
+            With this in mind, we've made it easy to configure whether or not this check is performed via the
+            "hibernate.shard.check_all_associated_objects_for_different_shards" property we referenced in the chapter
+            on configuration.  If this property is set to "true" a <classname>CrossShardRelationshipDetectingInterceptor</classname>
+            will be registered with every <classname>ShardedSession</classname> that is established.  Don't worry,
+            you can still register your own interceptor as well.  Our expectation is that most applications will have
+            this check enabled in their dev and qa environments and disabled in their staging, load and performance,
+            and production environments.
+        </para>
+    </sect1>
+    <sect1 id="shards-limitations-txns" revision="1">
+        <title>Distributed Transactions</title>
+        <para>
+            Hibernate Shards does not provide support for distributed transactions within
+            a non-managed environment.  If your application requires
+            distributed transactions you need to plug in a transaction management implementation that supports
+            distributed transactions.
+        </para>
+    </sect1>
+    <sect1 id="shards-limitations-interceptors" revision="1">
+        <title>Stateful Interceptors</title>
+        <para>
+            We've done our best to make sure that, by and large, Hibernate Core code runs just fine when using Hibernate
+            Shards. There are, unfortunately, exceptions, and one of those exceptions is when your application needs
+            to use an
+            <classname>org.hibernate.Interceptor</classname>
+            that maintains state.
+        </para>
+        <para>
+            Stateful interceptors need special handling because, under the hood, we're instantiating one
+            <classname>org.hibernate.SessionImpl</classname> per shard. If we want an
+            <classname>Interceptor</classname> associated with the
+            <classname>Session</classname>, we need to pass in whatever
+            <classname>Interceptor</classname> was provided when the
+            <classname>ShardedSession</classname> was created. If that
+            <classname>Interceptor</classname> is stateful, the
+            <classname>Interceptor</classname> state for one
+            <classname>Session</classname> will be visible in all
+            <classname>Sessions</classname>. When you consider the sorts of things that are typically done in stateful
+            <classname>Interceptors</classname> (auditing for example), you can see how this can pose a problem.
+        </para>
+        <para>
+            Our solution is to require users to provide a
+            <classname>StatefulInterceptorFactory</classname> when they establish their
+            <classname>Session</classname> objects (which are really
+            <classname>ShardedSessions</classname>).  If the provided
+            <classname>Interceptor</classname> implements this interface, Hibernate Shards will ensure that a
+            fresh instance of the type of <classname>Interceptor</classname>
+            returned by <classname>StatefulInterceptorFactory.newInstance()</classname>
+            will be passed to each <classname>Session</classname>
+            that is established under the hood.  Here's an example:
+            <programlisting><![CDATA[
+public class MyStatefulInterceptorFactory extends BaseStatefulInterceptorFactory {
+    public Interceptor newInstance() {
+        return new MyInterceptor();
+    }
+}
+]]></programlisting>
+
+        </para>
+        <para>
+            Many <classname>Interceptor</classname> implementations require a reference to the
+            <classname>Session</classname> with which they're associated. In the case of a stateful
+            <classname>Interceptor</classname>, you want your <classname>Interceptor</classname>
+            to have a reference to the real (shard-specific) <classname>Session</classname>, not the shard-aware
+            <classname>Session</classname>. In order to facilitate this, you have the choice of having the type of
+            <classname>Interceptor</classname> that is constructed by the
+            <classname>StatefulInterceptorFactory</classname> implement the
+            <classname>RequiresSession</classname> interface. If the
+            <classname>Interceptor</classname> constructed by the
+            <classname>StatefulInterceptorFactory</classname> implements this interface, Hibernate Shards will provide the
+            <classname>Interceptor</classname> with a reference to the real (shard-specific)
+            <classname>Session</classname> once the factory constructs it. This way your
+            <classname>Interceptor</classname> can safely and accurately interact with a speicific shard.  Here's an example:
+            <programlisting><![CDATA[
+public class MyStatefulInterceptor implements Interceptor, RequiresSession {
+    private Session session;
+
+    public void setSession(Session session) {
+        this.session = session;
+    }
+
+    ... // Interceptor interface impl
+}
+]]></programlisting>
+        </para>
+        <para>
+            Due to the basic nature of the problem we don't expect this to change anytime soon.
+        </para>
+    </sect1>
+    <sect1 id="shards-limitations-base-ids" revision="1">
+        <title>Objects With Ids That Are Base Types</title>
+        <para>
+            With Hibernate your model objects can use whatever they want as their ids so long as the id can be
+            represented by a <classname>Serializable</classname> (or autoboxed into a
+            <classname>Serializable</classname>). With Hibernate Shards you are slightly more constrained
+            because we don't support base types.
+        </para>
+        <para>
+            So this is no good:
+            <programlisting><![CDATA[
+public class WeatherReport {
+    private int weatherReportId;  // trouble
+
+    public int getWeatherReportId() {
+        return weatherReportId;
+    }
+
+    public void setWeatherReportId(int id) {
+        weatherReportId = id;
+    }
+}
+]]></programlisting>
+        </para>
+        <para>
+            But this is just lovely:
+            <programlisting><![CDATA[
+public class WeatherReport {
+    private Integer weatherReportId;  // goodness
+
+    public Integer getWeatherReportId() {
+        return weatherReportId;
+    }
+
+    public void setWeatherReportId(Integer id) {
+        weatherReportId = id;
+    }
+}
+]]></programlisting>
+        </para>
+        <para>
+            Do we have a good reason for this limitation? Not really. It's the result of an implementation
+            choice that has leaked out and made everyone's lives a tiny bit worse. If you simply must
+            use Hibernate Shards and you simply must model your ids with base types, don't call
+            <classname>Session.saveOrUpdate</classname>. We aim to address this leak soon and let you get back
+            to modeling whatever way you like (although for the record, we prefer object ids because
+            they make it easy to determine whether or not an object has had an id assigned).
+        </para>
+    </sect1>
+    <sect1 id="shards-limitations-replicated-data" revision="1">
+        <title>Replicated Data</title>
+        <para>
+            Even though this is a framework for horizontal partitioning, there is almost always
+            read-only (or at least slow changing) data that lives on every shard. If you're just
+            reading these entities we don't have a problem, but if you want to associate these
+            entities with sharded entities we run into trouble. Suppose you have a Country table
+            on every shard with the exact same data, and suppose WeatherReport has a Country member.
+            How do we guarantee that the Country you associate with that WeatherReport is associated
+            with the same shard as the WeatherReport? If we get it wrong we'll end up with a cross-shard
+            relationship, and that's bad.
+        </para>
+        <para>We have a number
+            of ideas about how to make this easy to deal with but we have not yet implemented any of them.
+            In the short term, we think your best bet is to either not create object relationships between
+            sharded entities and replicated entities. In otherwords, just model the relationship like
+            you would if you weren't using an OR Mapping tool. We know this is clunky and annoying.
+            We'll take care of it soon.
+        </para>
+    </sect1>
+</chapter>

Added: trunk/HibernateExt/shards/doc/reference/en/modules/querying.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/querying.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/querying.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="shards-querying">
+    <title>Querying</title>
+    <sect1 id="shards-querying-overview" revision="1">
+        <title>Overview</title>
+        <para>
+            Executing queries across shards can be hard.  In this chapter we'll discuss what works,
+            what doesn't, and what you can do to stay out of trouble.
+        </para>
+    </sect1>
+    <sect1 id="shards-querying-criteria" revision="1">
+        <title>Criteria</title>
+        <para>
+            As we discuss in the chapter on Limitations, we do not yet have a complete implementation of the
+            Hibernate Core API.  This limitation applies to <classname>ShardedCriteriaImpl</classname>,
+            which is a shard-aware implementation of the <classname>Criteria</classname> interface.
+            In this chapter we won't go into the details of specific things that haven't been implemented.
+            Rather, we're going to discuss the types of <classname>Criteria</classname> queries that are
+            problematic in a sharded environment.
+        </para>
+        <para>
+            Simply put, queries that do sorting are trouble.  Why?  Because we can't return a properly
+            sorted list without the ability to compare any value in the list to any other value in the list,
+            and the entire list isn't available until the results of the individual queries have been
+            collected in the application tier.  The sorting needs to take place inside Hibernate Shards, and
+            in order for this to happen we require that all objects returned by a <classname>Criteria</classname>
+            query with an order-by clause implement the <classname>Comparable</classname> interface.
+            If the type of the objects you return do not implement this exception you'll receive an
+            exception.
+        </para>
+        <para>
+            Distinct clauses are trouble as well.  So much trouble, in fact, that at the moment we don't
+            even support them.  Sorry about that.
+        </para>
+        <para>
+            On the other hand, while distinct and order-by are trouble, aggregation works just fine.
+            Consider the following example:
+            <programlisting><![CDATA[
+        // fetch the average of all temperatures recorded since last thursday
+        Criteria crit = session.createCriteria(WeatherReport.class);
+        crit.add(Restrictions.gt("timestamp", lastThursday));
+        crit.setProjection(Projections.avg("temperature"));
+        return crit.list();
+            ]]></programlisting>
+            In a single-shard environment this query can be easily answered, but in a multi-shard
+            environment it's a little bit trickier.  Why?  Because just getting the average from each
+            shard isn't enough to calculate the average across all shards.  In order to calculate this
+            piece of information we need not just the average but the number of records from each shard.
+            This is exactly what we do, and the performance hit (doing an extra count as part of
+            each query) is probably negligible.
+            Now, if we wanted the median
+            we'd be in trouble (just adding the count to the query would not provide enough information
+            to perform the calculation), but at the moment <classname>Criteria</classname> doesn't expose
+            a median function so we'll deal with that if and when it becomes and issue.
+        </para>
+    </sect1>
+    <sect1 id="shards-querying-hql" revision="1">
+        <title>HQL</title>
+        <para>
+            Our support for HQL is, at this point, not nearly as good as the support we have for <classname>Criteria</classname>
+            queries.  We have not yet implemented any extensions to the query parser, so we don't support
+            distinct, order-by, or aggregations.  This means you can only use HQL for very simple queries.  You're
+            probably better off staying clear of HQL in this release if you can help it.
+        </para>
+    </sect1>
+    <sect1 id="shards-querying-strategy" revision="1">
+        <title>Use of Shard Strategy When Querying</title>
+        <para>
+            The only component of your shard strategy that is consulted when executing a query (<classname>Criteria</classname>
+            or HQL) is the <classname>ShardAccessStrategy</classname>.  <classname>ShardSelectionStrategy</classname>
+            is ignored because executing a query doesn't create any new records in the database.  <classname>ShardResolutionStrategy</classname>
+            is ignored because we currently assume that you always want your query executed on all shards.  If this
+            isn't the case, the best thing to do is just downcast your <classname>Session</classname> to a <classname>ShardedSession</classname>
+            and dig out the shard-specific <classname>Session</classname>s you need.  Clunky, but it works.  We'll
+            come up with a better solution for this in later releases.
+        </para>
+    </sect1>
+</chapter>

Added: trunk/HibernateExt/shards/doc/reference/en/modules/resharding.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/resharding.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/resharding.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="shards-resharding">
+    <title>Resharding</title>
+    <para>
+        When an application's dataset grows beyond the capacity of the databases
+        originally allocated to the application it becomes necessary to add more databases, and
+        it is often desirable to redistribute the data across the shards (either to achieve
+        proper load balancing or to satisfy application invariants) - this is
+        called
+        resharding. Resharding is a complicated problem, and it has the potential to cause major
+        complications in the management of your production application if it is not considered during the design.
+        In order to ease some of the pain associated with resharding, Hibernate
+        Shards provides support for virtual shards.
+    </para>
+    <sect1 id="shards-resharding-virtual" revision="1">
+        <title>Virtual Shards</title>
+        <para>
+            In the general case, each object lives on a shard. Resharding consists
+            of two tasks: moving the object to another shard, and changing
+            object-shard mappings. The object-shard mapping is captured either by the shard ID
+            encoded into the object ID or by the internal logic of the shard
+            resolution strategy which the object uses. In the former case, resharding would require
+            changing all the object IDs and FKs. In the latter case, resharding could
+            require anything from changing the runtime configuration of a given
+            <classname>ShardResolutionStrategy</classname>
+            to changing the algorithm of the
+            <classname>ShardResolutionStrategy</classname>. Unfortunately, the problem of changing object-shard
+            mappings becomes even worse once we consider the fact that Hibernate Shards does not support cross-shard
+            relationships. This limitation prevents us from moving a subset of an object graph from one shard to
+            another.
+        </para>
+        <para>
+            The task of changing object-shard mappings can be simplified by adding a level
+            of indirection - each object lives on a virtual shard, and each virtual shard is mapped to
+            one physical shard. During design, developers must decide on the maximum number of physical shards
+            the application will ever require.  This maximum is then used as the number of virtual shards, and these
+            virtual shards are then mapped to the physical shards currently required by the application.
+            Since Hibernate
+            Shards'
+            <classname>ShardSelectionStrategy</classname>,
+            <classname>ShardResolutionStrategy</classname>, and
+            <classname>ShardEncodingIdentifierGenerator</classname>
+            all operate on virtual shards, the
+            objects will correctly be distributed across virtual shards. During resharding,
+            object-shard mappings can now simply be changed by changing virtual shard to physical shard
+            mappings.
+        </para>
+        <para>
+            If you're worried about correctly estimating the maximum number of physical shards your application
+            will ever require, aim high.  Virtual shards are cheap.  Down the road you'll be much better off with extra
+            virtual than if you have to add virtual shards.
+        </para>
+        <para>
+            In order to enable virtual sharding you need to create your <classname>ShardedConfiguration</classname>
+            with a Map from virtual shard ids to physical shard ids.  Here's an example where we have 4 virtual
+            shards mapped to 2 physical shards.
+<programlisting><![CDATA[
+Map<Integer, Integer> virtualShardMap = new HashMap<Integer, Integer>();
+virtualShardMap.put(0, 0);
+virtualShardMap.put(1, 0);
+virtualShardMap.put(2, 1);
+virtualShardMap.put(3, 1);
+ShardedConfiguration shardedConfig =
+    new ShardedConfiguration(
+        prototypeConfiguration,
+        configurations,
+        strategyFactory,
+        virtualShardMap);
+return shardedConfig.buildShardedSessionFactory();
+]]></programlisting>
+            In order to change the
+            virtual shard to physical shard mapping later on it is only necessary to change the
+            <classname>virtualShardToShardMap</classname> passed to this constructor.
+        </para>
+        <para>
+            We mentioned that the second task during resharding is moving data from one
+            physical shard to another. Hibernate Shards does not try to provide
+            automatic support for this as this is usually very application-specific, and
+            complexity varies based on the potential need for hot-resharding, deployment
+            architecture of the application, etc.
+        </para>
+    </sect1>
+</chapter>

Added: trunk/HibernateExt/shards/doc/reference/en/modules/shardstrategy.xml
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/modules/shardstrategy.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/modules/shardstrategy.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter id="shards-shardstrategy">
+    <title>Shard Strategy</title>
+    <sect1 id="shards-strategy-overview" revision="1">
+        <title>Overview</title>
+        <para>
+            Hibernate Shards gives you enormous flexibility in configuring how your data is distributed across your
+            shards and how your data is queried across your shards. The entry point for this configuration is the
+            <classname>org.hibernate.shards.strategy.ShardStrategy</classname> interface:
+            <programlisting><![CDATA[
+public interface ShardStrategy {
+    ShardSelectionStrategy getShardSelectionStrategy();
+    ShardResolutionStrategy getShardResolutionStrategy();
+    ShardAccessStrategy getShardAccessStrategy();
+}
+]]></programlisting>
+            As you can see, a
+            <classname>ShardStrategy</classname>
+            is comprised of three sub-strategies. We'll discuss each of these in turn.
+        </para>
+    </sect1>
+    <sect1 id="shards-strategy-shardaccess" revision="1">
+        <title>ShardAccessStrategy</title>
+        <para>
+            We'll start with the most simple of the strategies:
+            <classname>ShardAccessStrategy</classname>. Hibernate Shards uses the
+            <classname>ShardAccessStrategy</classname>
+            to determine how to apply database operations across multiple shards. The
+            <classname>ShardAccessStrategy</classname>
+            is consulted whenever you execute a query against your shards. We've already provided two implementations of
+            this interface that we expect will suffice for the majority of applications.
+        </para>
+        <sect2 id="shards-strategy-shardaccess-seq" revision="1">
+            <title>SequentialShardAccessStrategy</title>
+            <para>
+                <classname>SequentialShardAccessStrategy</classname>
+                behaves in the exact way that is implied by its name: queries are executed against your shards in
+                sequence. Depending on the types of queries you execute you may want to avoid this implementation
+                because it will execute queries against your shards in the same order every time. If you execute a lot
+                of row-limited, unordered queries this
+                <emphasis>could</emphasis>
+                result in poor utilization across your shards (shards that appear early in your list will get hammered
+                and shards that appear late will sit idly by, twiddling their shard-thumbs). If this is a concern you
+                should consider using the
+                <classname>LoadBalancedSequentialShardAccessStrategy</classname>
+                instead. This implementation receives a rotated view of your shards on each invocation, thereby
+                distributing query load evenly.
+            </para>
+        </sect2>
+        <sect2 id="shards-strategy-shardaccess-par" revision="1">
+            <title>ParallelShardAccessStrategy</title>
+            <para>
+                <classname>ParallelShardAccessStrategy</classname>
+                also behaves in the exact way that is implied by its name: queries are executed against your shards in
+                parallel. When you use this implementation you need to provide a
+                <classname>java.util.concurrent.ThreadPoolExecutor</classname>
+                that is suitable for the performance and throughput needs of your application.
+                Here's a simple example:
+                <programlisting><![CDATA[
+    ThreadFactory factory = new ThreadFactory() {
+        public Thread newThread(Runnable r) {
+            Thread t = Executors.defaultThreadFactory().newThread(r);
+            t.setDaemon(true);
+            return t;
+        }
+    };
+
+    ThreadPoolExecutor exec =
+        new ThreadPoolExecutor(
+            10,
+            50,
+            60,
+            TimeUnit.SECONDS,
+            new SynchronousQueue<Runnable>(),
+            factory);
+
+    return new ParallelShardAccessStrategy(exec);
+    ]]></programlisting>
+Please note that these are just sample values - proper thread pool configuration is beyond the scope of this document.  
+            </para>
+        </sect2>
+    </sect1>
+    <sect1 id="shards-strategy-shardselection" revision="1">
+        <title>ShardSelectionStrategy</title>
+        <para>
+            Hibernate Shards uses the
+            <classname>ShardSelectionStrategy</classname>
+            to determine the shard on which a new object should be created. It's entirely up to you to decide what you
+            want your implementation of this interface to look like, but we've provided a round-robin implementation to
+            get you started (<classname>RoundRobinShardSelectionStrategy</classname>). We expect many applications will
+            want to implement attribute-based sharding, so for our example
+            application that stores weather reports let's shard reports by the continents on which the reports originate:
+            <programlisting><![CDATA[
+public class WeatherReportShardSelectionStrategy implements ShardSelectionStrategy {
+    public ShardId selectShardIdForNewObject(Object obj) {
+        if(obj instanceof WeatherReport) {
+            return ((WeatherReport)obj).getContinent().getShardId();
+        }
+        throw new IllegalArgumentException();
+    }
+}
+]]></programlisting>
+
+        </para>
+        <para>
+            It's important to note that if a multi-level object graph is being saved via Hibernate's cascading
+            functionality, the
+            <classname>ShardSelectionStrategy</classname>
+            will only be consulted when saving the top-level object. All child objects will automatically be saved to
+            the same shard as the parent. You may find your
+            <classname>ShardSelectionStrategy</classname>
+            easier to implement if you prevent developers from creating new objects at more than one level in your
+            object hierarchy. You can accomplish this by making your
+            <classname>ShardSelectionStrategy</classname>
+            implementation aware of the top-level objects in your model and having it throw an exception if it
+            encounters an object that is not in this set. If you do not wish to impose this restriction that's fine,
+            just remember that if you're doing attribute-based shard selection, the attributes you use to make your
+            decision need to be available on every object that gets passed to session.save().
+        </para>
+    </sect1>
+    <sect1 id="shards-strategy-shardresolution" revision="1">
+        <title>ShardResolutionStrategy</title>
+        <para>
+            Hibernate Shards uses the
+            <classname>ShardResolutionStrategy</classname>
+            to determine the set of shards on which an object with a given id might reside. Let's go back to our weather
+            report application and suppose, for example, that each continent has a range of ids associated with it.
+            Whenever we assign an id to a WeatherReport we pick one that falls within the legal range for the continent
+            to which the WeatherReport belongs. Our
+            <classname>ShardResolutionStrategy</classname>
+            can use this information to identify which shard a WeatherReport resides on simply by looking at the id:
+            <programlisting><![CDATA[
+public class WeatherReportShardResolutionStrategy extends AllShardsShardResolutionStrategy {
+    public WeatherReportShardResolutionStrategy(List<ShardId> shardIds) {
+        super(shardIds);
+    }
+
+    public List<ShardId> selectShardIdsFromShardResolutionStrategyData(
+            ShardResolutionStrategyData srsd) {
+        if(srsd.getEntityName().equals(WeatherReport.class.getName())) {
+            return Continent.getContinentByReportId(srsd.getId()).getShardId();
+        }
+        return super.selectShardIdsFromShardResolutionStrategyData(srsd);
+    }
+}
+]]></programlisting>
+            It's worth pointing out that while we have not (yet) implemented a cache that maps entity name/id to shard,
+            the
+            <classname>ShardResolutionStrategy</classname>
+            would be an excellent place to plug in such a cache.
+        </para>
+        <para>
+            Shard Resolution is tightly tied to ID Generation. If you select an ID Generator for your class that encodes
+            the shard id in the id of the object, your
+            <classname>ShardResolutionStrategy</classname>
+            will never even be called. If you plan to only use ID Generators that encode the shard id in the ids of your
+            object you should use
+            <classname>AllShardsShardResolutionStrategy</classname>
+            as your
+            <classname>ShardResolutionStrategy</classname>.
+        </para>
+    </sect1>
+    <sect1 id="shards-strategy-idgen" revision="1">
+        <title>ID Generation</title>
+        <para>
+            Hibernate Sharding supports any ID generation strategy; the only requirement is that
+            object IDs have to be unique across all the shards. There are a few simple ID
+            generation strategies which support this requirement:
+            <itemizedlist>
+                <listitem>
+                    <para>
+                        <emphasis>Native ID generation</emphasis>
+                        - use Hibernate's
+                        <code>native</code>
+                        ID generation strategy, and configure your databases so
+                        that the IDs never collide. For example, if you are using
+                        <code>identity</code>
+                        ID generation, you have 5 databases across which you will
+                        evenly distribute the data, and you don't expect you will ever have more
+                        than 1 million records, you could configure database 0 to return IDs
+                        starting at 0, configure database 1 to return IDs starting at 200000,
+                        configure database 2 to return IDs starting at 400000, and so on. As long as
+                        your assumptions about the data are correct, the IDs of your objects would
+                        never collide.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <emphasis>Application-level UUID generation</emphasis>
+                        - by definition you
+                        don't have to worry about ID collisions, but you do need to be willing to
+                        deal with potentially unwieldy primary keys for your objects.
+                    </para>
+                    <para>
+                        Hibernate Shards provides an implementation of a simple, shard-aware UUID generator -
+                        <classname>ShardedUUIDGenerator</classname>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        <emphasis>Distributed hilo generation</emphasis>
+                        - the idea is to have a
+                        hilo table on only one shard, which ensures that the identifiers generated
+                        by the hi/lo algorithm are unique across all shards. Two main drawbacks of
+                        this approach are that the access to the hilo table can become the
+                        bottleneck in ID generation, and that storing the hilo table on a single
+                        database creates a single point of failure of the system.
+                    </para>
+                    <para>
+                        Hibernate Shards provides an implementation of a distributed hilo generation algorithm -
+                        <classname>ShardedTableHiLoGenerator</classname>.  This implementation is based on
+                        <classname>org.hibernate.id.TableHiLoGenerator</classname>, so for
+                        information on the expected structure of the database table on which the implementation
+                        depends please see the documentation for this class.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </para>
+        <para>
+            ID generation is also tightly tied with the shard resolution. The objective of shard
+            resolution is to find the shard an object lives on, given the object's ID. There are
+            two ways to accomplish this objective:
+            <itemizedlist>
+                <listitem>
+                    <para>Use the
+                        <classname>ShardResolutionStrategy</classname>, described above
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>Encode the shard ID into the object ID during the ID generation,
+                        and retrieve the shard ID during shard resolution
+                    </para>
+                </listitem>
+            </itemizedlist>
+            The main advantage of encoding the shard ID into the object ID is that it
+            enables Hibernate Shards
+            to resolve the shard from the object's ID much faster without database
+            lookups, cache lookups, etc. Hibernate Shards does not require any specific
+            algorithm for encoding/decoding of the shard ID - all you have to do is use an ID
+            generator that implements the
+            <classname>ShardEncodingIdentifierGenerator</classname>
+            interface. Of the two ID generators included with Hibernate Shards, the
+            <classname>ShardedUUIDGenerator</classname>
+            implements this interface.
+        </para>
+    </sect1>
+</chapter>

Added: trunk/HibernateExt/shards/doc/reference/en/styles/fopdf.xsl
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/styles/fopdf.xsl	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/styles/fopdf.xsl	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,519 @@
+<?xml version="1.0"?>
+
+<!--
+
+    This is the XSL FO configuration file for the Hibernate
+    Reference Documentation. It defines a custom titlepage and
+    the parameters for the A4 sized PDF printable output.
+
+    It took me days to figure out this stuff and fix most of
+    the obvious bugs in the DocBook XSL distribution. Some of
+    the workarounds might not be appropriate with a newer version
+    of DocBook XSL. This file is released as part of Hibernate,
+    hence LGPL licensed.
+
+    christian at hibernate.org
+
+-->
+
+<!DOCTYPE xsl:stylesheet [
+    <!ENTITY db_xsl_path        "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet
+    version="1.0"
+    xmlns="http://www.w3.org/TR/xhtml1/transitional"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:fo="http://www.w3.org/1999/XSL/Format"
+    exclude-result-prefixes="#default">
+
+    <xsl:import href="&db_xsl_path;/fo/docbook.xsl"/>
+
+    <!--###################################################
+                       Custom Title Page
+        ################################################### -->
+
+    <xsl:template name="book.titlepage.recto">
+        <fo:block>
+            <fo:table table-layout="fixed" width="175mm">
+                <fo:table-column column-width="175mm"/>
+                <fo:table-body>
+                    <fo:table-row>
+                        <fo:table-cell text-align="center">
+                            <fo:block>
+                                <fo:external-graphic src="file:images/hibernate_logo_a.png"/>
+                            </fo:block>
+                            <fo:block font-family="Helvetica" font-size="22pt" padding-before="10mm">
+                                <xsl:value-of select="bookinfo/title"/>
+                            </fo:block>
+                            <fo:block font-family="Helvetica" font-size="18pt" padding-before="10mm">
+                                <xsl:value-of select="bookinfo/subtitle"/>
+                            </fo:block>
+                            <fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
+                                Version:
+                                <xsl:value-of select="bookinfo/releaseinfo"/>
+                            </fo:block>
+                        </fo:table-cell>
+                    </fo:table-row>
+                </fo:table-body>
+            </fo:table>
+        </fo:block>
+    </xsl:template>
+
+    <!-- Prevent blank pages in output -->
+    <xsl:template name="book.titlepage.before.verso">
+    </xsl:template>
+    <xsl:template name="book.titlepage.verso">
+    </xsl:template>
+    <xsl:template name="book.titlepage.separator">
+    </xsl:template>
+
+    <!--###################################################
+                          Header
+        ################################################### -->
+
+    <!-- More space in the center header for long text -->
+    <xsl:attribute-set name="header.content.properties">
+        <xsl:attribute name="font-family">
+            <xsl:value-of select="$body.font.family"/>
+        </xsl:attribute>
+        <xsl:attribute name="margin-left">-5em</xsl:attribute>
+        <xsl:attribute name="margin-right">-5em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!--###################################################
+                          Custom Footer
+        ################################################### -->
+
+    <!-- This footer prints the Hibernate version number on the left side -->
+    <xsl:template name="footer.content">
+        <xsl:param name="pageclass" select="''"/>
+        <xsl:param name="sequence" select="''"/>
+        <xsl:param name="position" select="''"/>
+        <xsl:param name="gentext-key" select="''"/>
+
+        <xsl:variable name="Version">
+            <xsl:choose>
+                <xsl:when test="//releaseinfo">
+                    <xsl:text>Hibernate </xsl:text>
+                    <xsl:value-of select="//releaseinfo"/>
+                </xsl:when>
+                <xsl:otherwise>
+                    <!-- nop -->
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+
+        <xsl:choose>
+            <xsl:when test="$sequence='blank'">
+                <xsl:choose>
+                    <xsl:when test="$double.sided != 0 and $position = 'left'">
+                        <xsl:value-of select="$Version"/>
+                    </xsl:when>
+
+                    <xsl:when test="$double.sided = 0 and $position = 'center'">
+                        <!-- nop -->
+                    </xsl:when>
+
+                    <xsl:otherwise>
+                        <fo:page-number/>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </xsl:when>
+
+            <xsl:when test="$pageclass='titlepage'">
+                <!-- nop: other titlepage sequences have no footer -->
+            </xsl:when>
+
+            <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='left'">
+                <fo:page-number/>
+            </xsl:when>
+
+            <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='right'">
+                <fo:page-number/>
+            </xsl:when>
+
+            <xsl:when test="$double.sided = 0 and $position='right'">
+                <fo:page-number/>
+            </xsl:when>
+
+            <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='left'">
+                <xsl:value-of select="$Version"/>
+            </xsl:when>
+
+            <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='right'">
+                <xsl:value-of select="$Version"/>
+            </xsl:when>
+
+            <xsl:when test="$double.sided = 0 and $position='left'">
+                <xsl:value-of select="$Version"/>
+            </xsl:when>
+
+            <xsl:otherwise>
+                <!-- nop -->
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <!--###################################################
+                       Custom Toc Line
+        ################################################### -->
+    
+    <!-- Improve the TOC. -->
+    <xsl:template name="toc.line">
+        <xsl:variable name="id">
+            <xsl:call-template name="object.id"/>
+        </xsl:variable>
+
+        <xsl:variable name="label">
+            <xsl:apply-templates select="." mode="label.markup"/>
+        </xsl:variable>
+
+        <fo:block text-align-last="justify"
+            end-indent="{$toc.indent.width}pt"
+            last-line-end-indent="-{$toc.indent.width}pt">
+            <fo:inline keep-with-next.within-line="always">
+                <fo:basic-link internal-destination="{$id}">
+
+                    <!-- Chapter titles should be bold. -->
+                    <xsl:choose>
+                        <xsl:when test="local-name(.) = 'chapter'">
+                            <xsl:attribute name="font-weight">bold</xsl:attribute>
+                        </xsl:when>
+                    </xsl:choose>
+
+                    <xsl:if test="$label != ''">
+                        <xsl:copy-of select="$label"/>
+                        <xsl:value-of select="$autotoc.label.separator"/>
+                    </xsl:if>
+                    <xsl:apply-templates select="." mode="titleabbrev.markup"/>
+                </fo:basic-link>
+            </fo:inline>
+            <fo:inline keep-together.within-line="always">
+                <xsl:text> </xsl:text>
+                <fo:leader leader-pattern="dots"
+                    leader-pattern-width="3pt"
+                    leader-alignment="reference-area"
+                    keep-with-next.within-line="always"/>
+                <xsl:text> </xsl:text>
+                <fo:basic-link internal-destination="{$id}">
+                    <fo:page-number-citation ref-id="{$id}"/>
+                </fo:basic-link>
+            </fo:inline>
+        </fo:block>
+    </xsl:template>
+
+    <!--###################################################
+                          Extensions
+        ################################################### -->
+
+    <!-- These extensions are required for table printing and other stuff -->
+    <xsl:param name="use.extensions">1</xsl:param>
+    <xsl:param name="tablecolumns.extension">0</xsl:param>
+    <!-- FOP provide only PDF Bookmarks at the moment -->
+    <xsl:param name="fop.extensions">1</xsl:param>
+
+    <!--###################################################
+                          Table Of Contents
+        ################################################### -->
+
+    <!-- Generate the TOCs for named components only -->
+    <xsl:param name="generate.toc">
+        book   toc
+    </xsl:param>
+    
+    <!-- Show only Sections up to level 3 in the TOCs -->
+    <xsl:param name="toc.section.depth">3</xsl:param>
+    
+    <!-- Dot and Whitespace as separator in TOC between Label and Title-->
+    <xsl:param name="autotoc.label.separator" select="'.  '"/>
+
+
+    <!--###################################################
+                       Paper & Page Size
+        ################################################### -->
+    
+    <!-- Paper type, no headers on blank pages, no double sided printing -->
+    <xsl:param name="paper.type" select="'A4'"/>
+    <xsl:param name="double.sided">0</xsl:param>
+    <xsl:param name="headers.on.blank.pages">0</xsl:param>
+    <xsl:param name="footers.on.blank.pages">0</xsl:param>
+
+    <!-- Space between paper border and content (chaotic stuff, don't touch) -->
+    <xsl:param name="page.margin.top">5mm</xsl:param>
+    <xsl:param name="region.before.extent">10mm</xsl:param>
+    <xsl:param name="body.margin.top">10mm</xsl:param>
+
+    <xsl:param name="body.margin.bottom">15mm</xsl:param>
+    <xsl:param name="region.after.extent">10mm</xsl:param>
+    <xsl:param name="page.margin.bottom">0mm</xsl:param>
+
+    <xsl:param name="page.margin.outer">18mm</xsl:param>
+    <xsl:param name="page.margin.inner">18mm</xsl:param>
+
+    <!-- No intendation of Titles -->
+    <xsl:param name="title.margin.left">0pc</xsl:param>
+
+    <!--###################################################
+                       Fonts & Styles
+        ################################################### -->
+
+    <!-- Default Font size -->
+    <xsl:param name="body.font.master">11</xsl:param>
+
+    <!-- Line height in body text -->
+    <xsl:param name="line-height">1.4</xsl:param>
+
+    <!-- Monospaced fonts are smaller than regular text -->
+    <xsl:attribute-set name="monospace.properties">
+        <xsl:attribute name="font-family">
+            <xsl:value-of select="$monospace.font.family"/>
+        </xsl:attribute>
+        <xsl:attribute name="font-size">0.8em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!--###################################################
+                       Tables
+        ################################################### -->
+
+    <!-- The table width should be adapted to the paper size -->
+    <xsl:param name="default.table.width">17.4cm</xsl:param>
+
+    <!-- Some padding inside tables -->
+    <xsl:attribute-set name="table.cell.padding">
+        <xsl:attribute name="padding-left">4pt</xsl:attribute>
+        <xsl:attribute name="padding-right">4pt</xsl:attribute>
+        <xsl:attribute name="padding-top">4pt</xsl:attribute>
+        <xsl:attribute name="padding-bottom">4pt</xsl:attribute>
+    </xsl:attribute-set>
+    
+    <!-- Only hairlines as frame and cell borders in tables -->
+    <xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
+    <xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
+
+    <!--###################################################
+                             Labels
+        ################################################### -->
+
+    <!-- Label Chapters and Sections (numbering) -->
+    <xsl:param name="chapter.autolabel">1</xsl:param>
+    <xsl:param name="section.autolabel" select="1"/>
+    <xsl:param name="section.label.includes.component.label" select="1"/>
+
+    <!-- Label only Sections up to level 2 -->
+    <xsl:param name="local.l10n.xml" select="document('')"/>
+    <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+        <l:l10n language="en">
+            <l:context name="title-numbered">
+                <l:template name="sect3" text="%t"/>
+                <l:template name="sect4" text="%t"/>
+                <l:template name="sect5" text="%t"/>
+            </l:context>
+            <l:context name="section-xref-numbered">
+                <l:template name="sect3" text="the section called %t"/>
+                <l:template name="sect4" text="the section called %t"/>
+                <l:template name="sect5" text="the section called %t"/>
+            </l:context>
+        </l:l10n>
+    </l:i18n>
+    
+    <!--###################################################
+                             Titles
+        ################################################### -->
+    
+    <!-- Chapter title size -->
+    <xsl:attribute-set name="chapter.titlepage.recto.style">
+        <xsl:attribute name="text-align">left</xsl:attribute>
+        <xsl:attribute name="font-weight">bold</xsl:attribute>
+        <xsl:attribute name="font-size">
+            <xsl:value-of select="$body.font.master * 1.8"/>
+            <xsl:text>pt</xsl:text>
+        </xsl:attribute>
+    </xsl:attribute-set>
+
+    <!-- Why is the font-size for chapters hardcoded in the XSL FO templates? 
+        Let's remove it, so this sucker can use our attribute-set only... -->
+    <xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
+        <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
+            xsl:use-attribute-sets="chapter.titlepage.recto.style">
+            <xsl:call-template name="component.title">
+                <xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
+            </xsl:call-template>
+        </fo:block>
+    </xsl:template>
+    
+    <!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
+    <xsl:attribute-set name="section.title.level1.properties">
+        <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
+        <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
+        <xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
+        <xsl:attribute name="font-size">
+            <xsl:value-of select="$body.font.master * 1.5"/>
+            <xsl:text>pt</xsl:text>
+        </xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+    </xsl:attribute-set>
+    <xsl:attribute-set name="section.title.level2.properties">
+        <xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
+        <xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
+        <xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
+        <xsl:attribute name="font-size">
+            <xsl:value-of select="$body.font.master * 1.25"/>
+            <xsl:text>pt</xsl:text>
+        </xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+    </xsl:attribute-set>
+    <xsl:attribute-set name="section.title.level3.properties">
+        <xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
+        <xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
+        <xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
+        <xsl:attribute name="font-size">
+            <xsl:value-of select="$body.font.master * 1.0"/>
+            <xsl:text>pt</xsl:text>
+        </xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!-- Titles of formal objects (tables, examples, ...) -->
+    <xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
+        <xsl:attribute name="font-weight">bold</xsl:attribute>
+        <xsl:attribute name="font-size">
+            <xsl:value-of select="$body.font.master"/>
+            <xsl:text>pt</xsl:text>
+        </xsl:attribute>
+        <xsl:attribute name="hyphenate">false</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.6em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.8em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!--###################################################
+                          Programlistings
+        ################################################### -->
+    
+    <!-- Verbatim text formatting (programlistings) -->
+    <xsl:attribute-set name="verbatim.properties">
+        <xsl:attribute name="space-before.minimum">1em</xsl:attribute>
+        <xsl:attribute name="space-before.optimum">1em</xsl:attribute>
+        <xsl:attribute name="space-before.maximum">1em</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+        <xsl:attribute name="border-color">#444444</xsl:attribute>
+        <xsl:attribute name="border-style">solid</xsl:attribute>
+        <xsl:attribute name="border-width">0.1pt</xsl:attribute>
+        <xsl:attribute name="padding-top">0.5em</xsl:attribute>
+        <xsl:attribute name="padding-left">0.5em</xsl:attribute>
+        <xsl:attribute name="padding-right">0.5em</xsl:attribute>
+        <xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
+        <xsl:attribute name="margin-left">0.5em</xsl:attribute>
+        <xsl:attribute name="margin-right">0.5em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!-- Shade (background) programlistings -->
+    <xsl:param name="shade.verbatim">1</xsl:param>
+    <xsl:attribute-set name="shade.verbatim.style">
+        <xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!--###################################################
+                             Callouts
+        ################################################### -->
+
+    <!-- We want to use callouts... -->
+    <xsl:param name="callout.extensions">1</xsl:param>
+
+    <!-- Place callout bullets at this column in programmlisting.-->
+    <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+    <!--
+        No, don't use crappy graphics for the callout bullets. This setting
+        enables some weird Unicode rendering for some fancy bullet points
+        in callouts. By default, this can only count to 10 and produces
+        strange results if you ever have more than 10 callouts for one
+        programlisting. We will fix that next.
+    -->
+    <xsl:param name="callout.graphics">0</xsl:param>
+
+    <!--
+        Again, fun with DocBook XSL: The callout bullets are rendered in
+        two places: In the programlisting itself and in the list below
+        the listing, with the actual callout text. The rendering in the
+        programlisting is some XSL transformer extension (e.g. a Saxon
+        extension), so we can't change that without messing with the
+        extensions. We only can turn it off by setting this limit to
+        zero, then, a simple bracket style like "(3)" and "(4)" will
+        be used in the programlisting.
+    -->
+    <xsl:param name="callout.unicode.number.limit" select="'0'"></xsl:param>
+
+    <!--
+        The callout bullets in the actual callout list will be rendered
+        with an XSL FO template. The default template is broken: limited to 10
+        nice looking Unicode bullet points and then it doesn't print anything,
+        the fallback doesn't work. We implement our own template, which is not
+        as complicated, more ugly, but works. As always, function is more
+        important than form.
+    -->
+    <xsl:template name="callout-bug">
+        <xsl:param name="conum" select='1'/>
+        <fo:inline
+            color="black"
+            padding-top="0.1em"
+            padding-bottom="0.1em"
+            padding-start="0.2em"
+            padding-end="0.2em"
+            baseline-shift="0.1em"
+            font-family="{$monospace.font.family}"
+            font-weight="bold"
+            font-size="75%">
+            <xsl:text>(</xsl:text>
+            <xsl:value-of select="$conum"/>
+            <xsl:text>)</xsl:text>
+        </fo:inline>
+
+    </xsl:template>
+
+    <!--###################################################
+                              Misc
+        ################################################### -->
+
+    <!-- Correct placement of titles for figures and examples. -->
+    <xsl:param name="formal.title.placement">
+        figure after
+        example before
+        equation before
+        table before
+        procedure before
+    </xsl:param>
+    
+    <!-- Format Variable Lists as Blocks (prevents horizontal overflow). -->
+    <xsl:param name="variablelist.as.blocks">1</xsl:param>
+
+    <!-- The horrible list spacing problems, this is much better. -->
+    <xsl:attribute-set name="list.block.spacing">
+        <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
+        <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
+        <xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
+        <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+        <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+    </xsl:attribute-set>
+
+    <!-- Newer DocBook XSL apparently thinks that some sections are by
+         default "draft" status, and this idiotic thing is by default
+         also set to "maybe", so it spits out a lot of errors with the
+         latest FOP as the XSL/FO styles have references to some draft
+         watermarks, which you actually don't want in the first place.
+         Turn this crap off. If you have to work with the "status"
+         attribute, don't.
+    -->
+    <xsl:param name="draft.mode" select="'no'"/>
+
+</xsl:stylesheet>

Added: trunk/HibernateExt/shards/doc/reference/en/styles/html.css
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/styles/html.css	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/styles/html.css	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,97 @@
+A {
+    color: #003399;
+}
+
+A:active {
+    color: #003399;
+}
+
+A:visited {
+    color: #888888;
+}
+
+P, OL, UL, LI, DL, DT, DD, BLOCKQUOTE {
+    color: #000000;
+}
+
+TD, TH, SPAN {
+    color: #000000;
+}
+
+BLOCKQUOTE {
+    margin-right: 0px;
+}
+
+
+H1, H2, H3, H4, H5, H6    {
+    color: #000000;
+    font-weight:500;
+    margin-top:10px;
+    padding-top:15px;
+}
+
+TABLE  {
+    border-collapse: collapse;
+    border-spacing:0;
+    border: 1px thin black;
+    empty-cells: hide;
+}
+
+TD  {
+    padding: 4pt;
+}
+
+H1 { font-size: 150%; }
+H2 { font-size: 140%; }
+H3 { font-size: 110%; font-weight: bold; }
+H4 { font-size: 110%; font-weight: bold;}
+H5 { font-size: 100%; font-style: italic; }
+H6 { font-size: 100%; font-style: italic; }
+
+TT {
+font-size: 90%;
+    font-family: "Courier New", Courier, monospace;
+    color: #000000;
+}
+
+PRE {
+font-size: 100%;
+    padding: 5px;
+    border-style: solid;
+    border-width: 1px;
+    border-color: #CCCCCC;
+    background-color: #F4F4F4;
+}
+
+UL, OL, LI {
+    list-style: disc;
+}
+
+HR  {
+    width: 100%;
+    height: 1px;
+    background-color: #CCCCCC;
+    border-width: 0px;
+    padding: 0px;
+    color: #CCCCCC;
+}
+
+.variablelist { 
+    padding-top: 10; 
+    padding-bottom:10; 
+    margin:0;
+}
+
+.itemizedlist, UL { 
+    padding-top: 0; 
+    padding-bottom:0; 
+    margin:0; 
+}
+
+.term { 
+    font-weight:bold;
+}
+
+
+
+    

Added: trunk/HibernateExt/shards/doc/reference/en/styles/html.xsl
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/styles/html.xsl	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/styles/html.xsl	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+
+<!--
+
+    This is the XSL HTML configuration file for the Hibernate
+    Reference Documentation.
+
+    It took me days to figure out this stuff and fix most of
+    the obvious bugs in the DocBook XSL distribution. Some of
+    the workarounds might not be appropriate with a newer version
+    of DocBook XSL. This file is released as part of Hibernate,
+    hence LGPL licensed.
+
+    christian at hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+    <!ENTITY db_xsl_path        "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="1.0"
+                xmlns="http://www.w3.org/TR/xhtml1/transitional"
+                exclude-result-prefixes="#default">
+                
+<xsl:import href="&db_xsl_path;/html/docbook.xsl"/>
+
+<!--###################################################
+                     HTML Settings
+    ################################################### -->   
+
+    <xsl:param name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+    <!-- These extensions are required for table printing and other stuff -->
+    <xsl:param name="use.extensions">1</xsl:param>
+    <xsl:param name="tablecolumns.extension">0</xsl:param>
+    <xsl:param name="callout.extensions">1</xsl:param>
+    <xsl:param name="graphicsize.extension">0</xsl:param>
+
+<!--###################################################
+                      Table Of Contents
+    ################################################### -->   
+
+    <!-- Generate the TOCs for named components only -->
+    <xsl:param name="generate.toc">
+        book   toc
+    </xsl:param>
+    
+    <!-- Show only Sections up to level 3 in the TOCs -->
+    <xsl:param name="toc.section.depth">3</xsl:param>
+    
+<!--###################################################
+                         Labels
+    ################################################### -->   
+
+    <!-- Label Chapters and Sections (numbering) -->
+    <xsl:param name="chapter.autolabel">1</xsl:param>
+    <xsl:param name="section.autolabel" select="1"/>
+    <xsl:param name="section.label.includes.component.label" select="1"/>
+
+<!--###################################################
+                         Callouts
+    ################################################### -->
+
+    <!-- Don't use graphics, use a simple number style -->
+    <xsl:param name="callout.graphics">0</xsl:param>
+
+    <!-- Place callout marks at this column in annotated areas -->
+    <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+                          Misc
+    ################################################### -->   
+
+    <!-- Placement of titles -->
+    <xsl:param name="formal.title.placement">
+        figure after
+        example before
+        equation before
+        table before
+        procedure before
+    </xsl:param>    
+    
+</xsl:stylesheet>

Added: trunk/HibernateExt/shards/doc/reference/en/styles/html_chunk.xsl
===================================================================
--- trunk/HibernateExt/shards/doc/reference/en/styles/html_chunk.xsl	                        (rev 0)
+++ trunk/HibernateExt/shards/doc/reference/en/styles/html_chunk.xsl	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+
+<!--
+
+    This is the XSL HTML configuration file for the Hibernate
+    Reference Documentation.
+
+    It took me days to figure out this stuff and fix most of
+    the obvious bugs in the DocBook XSL distribution. Some of
+    the workarounds might not be appropriate with a newer version
+    of DocBook XSL. This file is released as part of Hibernate,
+    hence LGPL licensed.
+
+    christian at hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+    <!ENTITY db_xsl_path        "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version="1.0"
+                xmlns="http://www.w3.org/TR/xhtml1/transitional"
+                exclude-result-prefixes="#default">
+                
+<xsl:import href="&db_xsl_path;/html/chunk.xsl"/>
+
+<!--###################################################
+                     HTML Settings
+    ################################################### -->   
+
+    <xsl:param name="chunk.section.depth">'5'</xsl:param>
+    <xsl:param name="use.id.as.filename">'1'</xsl:param>
+    <xsl:param name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+    <!-- These extensions are required for table printing and other stuff -->
+    <xsl:param name="use.extensions">1</xsl:param>
+    <xsl:param name="tablecolumns.extension">0</xsl:param>
+    <xsl:param name="callout.extensions">1</xsl:param>
+    <xsl:param name="graphicsize.extension">0</xsl:param>
+    
+<!--###################################################
+                      Table Of Contents
+    ################################################### -->   
+
+    <!-- Generate the TOCs for named components only -->
+    <xsl:param name="generate.toc">
+        book   toc
+    </xsl:param>
+    
+    <!-- Show only Sections up to level 3 in the TOCs -->
+    <xsl:param name="toc.section.depth">3</xsl:param>
+
+<!--###################################################
+                         Labels
+    ################################################### -->   
+
+    <!-- Label Chapters and Sections (numbering) -->
+    <xsl:param name="chapter.autolabel">1</xsl:param>
+    <xsl:param name="section.autolabel" select="1"/>
+    <xsl:param name="section.label.includes.component.label" select="1"/>
+                
+<!--###################################################
+                         Callouts
+    ################################################### -->   
+
+    <!-- Don't use graphics, use a simple number style -->
+    <xsl:param name="callout.graphics">0</xsl:param>
+
+    <!-- Place callout marks at this column in annotated areas -->
+    <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+                          Misc
+    ################################################### -->   
+
+    <!-- Placement of titles -->
+    <xsl:param name="formal.title.placement">
+        figure after
+        example before
+        equation before
+        table before
+        procedure before
+    </xsl:param>    
+    
+</xsl:stylesheet>

Added: trunk/HibernateExt/shards/etc/hibernate.properties
===================================================================
--- trunk/HibernateExt/shards/etc/hibernate.properties	                        (rev 0)
+++ trunk/HibernateExt/shards/etc/hibernate.properties	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,472 @@
+######################
+### Query Language ###
+######################
+
+## define query language constants / function names
+
+hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N'
+
+
+## select the classic query parser
+
+#hibernate.query.factory_class org.hibernate.hql.classic.ClassicQueryTranslatorFactory
+
+hibernate.format_sql true
+
+
+
+#################
+### Platforms ###
+#################
+
+## JNDI Datasource
+
+#hibernate.connection.datasource jdbc/test
+#hibernate.connection.username db2
+#hibernate.connection.password db2
+
+
+## HypersonicSQL
+
+hibernate.dialect org.hibernate.dialect.HSQLDialect
+hibernate.connection.driver_class org.hsqldb.jdbcDriver
+hibernate.connection.username sa
+hibernate.connection.password
+hibernate.connection.url jdbc:hsqldb:hsql://localhost
+hibernate.connection.url jdbc:hsqldb:test
+hibernate.connection.url jdbc:hsqldb:.
+
+
+## MySQL
+
+#hibernate.dialect org.hibernate.dialect.MySQLDialect
+#hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
+#hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
+#hibernate.connection.driver_class com.mysql.jdbc.Driver
+#hibernate.connection.url jdbc:mysql:///test
+#hibernate.connection.username emmanuel
+#hibernate.connection.password
+
+
+## Oracle
+
+#hibernate.dialect org.hibernate.dialect.OracleDialect
+#hibernate.dialect org.hibernate.dialect.Oracle9Dialect
+#hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver
+#hibernate.connection.username ora
+#hibernate.connection.password ora
+#hibernate.connection.url jdbc:oracle:thin:@localhost:1521:test
+
+
+## PostgreSQL
+
+#hibernate.dialect org.hibernate.dialect.PostgreSQLDialect
+#hibernate.connection.driver_class org.postgresql.Driver
+#hibernate.connection.url jdbc:postgresql:annotations
+#hibernate.connection.username postgres
+#hibernate.connection.password hibernate
+#hibernate.query.substitutions yes 'Y', no 'N'
+
+
+## DB2
+
+#hibernate.dialect org.hibernate.dialect.DB2Dialect
+#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
+#hibernate.connection.url jdbc:db2:test
+#hibernate.connection.username db2
+#hibernate.connection.password db2
+
+## TimesTen (not supported yet)
+
+#hibernate.dialect org.hibernate.dialect.TimesTenDialect
+#hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver
+#hibernate.connection.url jdbc:timesten:direct:test
+#hibernate.connection.username
+#hibernate.connection.password 
+
+## DB2/400
+
+#hibernate.dialect org.hibernate.dialect.DB2400Dialect
+#hibernate.connection.username user
+#hibernate.connection.password password
+
+## Native driver
+#hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
+#hibernate.connection.url jdbc:db2://systemname
+
+## Toolbox driver
+#hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver
+#hibernate.connection.url jdbc:as400://systemname
+
+
+## Derby (Not supported!)
+
+#hibernate.dialect org.hibernate.dialect.DerbyDialect
+#hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver
+#hibernate.connection.username
+#hibernate.connection.password
+#hibernate.connection.url jdbc:derby:/test;create=true
+
+
+## Sybase
+
+#hibernate.dialect org.hibernate.dialect.SybaseDialect
+#hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver
+#hibernate.connection.username sa
+#hibernate.connection.password sasasa
+#hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb
+
+
+## Mckoi SQL
+
+#hibernate.dialect org.hibernate.dialect.MckoiDialect
+#hibernate.connection.driver_class com.mckoi.JDBCDriver
+#hibernate.connection.url jdbc:mckoi:///
+#hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.00/db.conf
+#hibernate.connection.username admin
+#hibernate.connection.password nimda
+
+
+## SAP DB
+
+#hibernate.dialect org.hibernate.dialect.SAPDBDialect
+#hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB
+#hibernate.connection.url jdbc:sapdb://localhost/TST
+#hibernate.connection.username TEST
+#hibernate.connection.password TEST
+#hibernate.query.substitutions yes 'Y', no 'N'
+
+
+## MS SQL Server
+
+#hibernate.dialect org.hibernate.dialect.SQLServerDialect
+#hibernate.connection.username sa
+#hibernate.connection.password sa
+
+## JSQL Driver
+#hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver
+#hibernate.connection.url jdbc:JSQLConnect://1E1/test
+
+## JTURBO Driver
+#hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver
+#hibernate.connection.url jdbc:JTurbo://1E1:1433/test
+
+## WebLogic Driver
+#hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver
+#hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433
+
+## Microsoft Driver (not recommended!)
+#hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver
+#hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor
+
+## jTDS (since version 0.9)
+#hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver
+#hibernate.connection.url jdbc:jtds:sqlserver://1E1/test
+
+## Interbase
+
+#hibernate.dialect org.hibernate.dialect.InterbaseDialect
+#hibernate.connection.username sysdba
+#hibernate.connection.password masterkey
+
+## DO NOT specify hibernate.connection.sqlDialect
+
+## InterClient
+
+#hibernate.connection.driver_class interbase.interclient.Driver
+#hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb
+
+## Pure Java
+
+#hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver
+#hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb
+
+
+## Pointbase
+
+#hibernate.dialect org.hibernate.dialect.PointbaseDialect
+#hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver
+#hibernate.connection.url jdbc:pointbase:embedded:sample
+#hibernate.connection.username PBPUBLIC
+#hibernate.connection.password PBPUBLIC
+
+
+
+#################################
+### Hibernate Connection Pool ###
+#################################
+
+hibernate.connection.pool_size 1
+
+
+
+###########################
+### C3P0 Connection Pool###
+###########################
+
+#hibernate.c3p0.max_size 2
+#hibernate.c3p0.min_size 2
+#hibernate.c3p0.timeout 5000
+#hibernate.c3p0.max_statements 100
+#hibernate.c3p0.idle_test_period 3000
+#hibernate.c3p0.acquire_increment 2
+#hibernate.c3p0.validate false
+
+
+
+##############################
+### Proxool Connection Pool###
+##############################
+
+## Properties for external configuration of Proxool
+
+hibernate.proxool.pool_alias pool1
+
+## Only need one of the following
+
+#hibernate.proxool.existing_pool true
+#hibernate.proxool.xml proxool.xml
+#hibernate.proxool.properties proxool.properties
+
+
+
+#################################
+### Plugin ConnectionProvider ###
+#################################
+
+## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics)
+
+#hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider
+#hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider
+#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider
+#hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider
+#hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider
+
+
+
+#######################
+### Transaction API ###
+#######################
+
+## Enable automatic flush during the JTA beforeCompletion() callback
+## (This setting is relevant with or without the Transaction API)
+
+#hibernate.transaction.flush_before_completion
+
+
+## Enable automatic session close at the end of transaction
+## (This setting is relevant with or without the Transaction API)
+
+#hibernate.transaction.auto_close_session
+
+
+## the Transaction API abstracts application code from the underlying JTA or JDBC transactions
+
+#hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory
+#hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory
+
+
+## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI
+## default is java:comp/UserTransaction
+## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class
+
+#jta.UserTransaction jta/usertransaction
+#jta.UserTransaction javax.transaction.UserTransaction
+#jta.UserTransaction UserTransaction
+
+
+## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager
+
+#hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup
+#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup
+#hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup
+#hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup
+#hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup
+
+
+
+##############################
+### Miscellaneous Settings ###
+##############################
+
+## print all generated SQL to the console
+
+#hibernate.show_sql true
+
+
+## add comments to the generated SQL
+
+#hibernate.use_sql_comments true
+
+
+## generate statistics
+
+#hibernate.generate_statistics true
+
+
+## auto schema export
+
+#hibernate.hbm2ddl.auto create-drop
+#hibernate.hbm2ddl.auto create
+#hibernate.hbm2ddl.auto update
+
+
+## specify a default schema and catalog for unqualified tablenames
+
+#hibernate.default_schema test
+#hibernate.default_catalog test
+
+
+## enable ordering of SQL UPDATEs by primary key
+
+hibernate.order_updates true
+
+
+## set the maximum depth of the outer join fetch tree
+
+hibernate.max_fetch_depth 1
+
+
+## set the default batch size for batch fetching
+
+hibernate.default_batch_fetch_size 100
+
+
+## rollback generated identifier values of deleted entities to default values
+
+#hibernate.use_identifer_rollback true
+
+
+## enable CGLIB reflection optimizer (enabled by default)
+
+#hibernate.cglib.use_reflection_optimizer false
+
+
+
+#####################
+### JDBC Settings ###
+#####################
+
+## specify a JDBC isolation level
+
+#hibernate.connection.isolation 4
+
+
+## enable JDBC autocommit (not recommended!)
+
+#hibernate.connection.autocommit true
+
+
+## set the JDBC fetch size
+
+#hibernate.jdbc.fetch_size 25
+
+
+## set the maximum JDBC 2 batch size (a nonzero value enables batching)
+
+#hibernate.jdbc.batch_size 0
+
+
+## enable batch updates even for versioned data
+
+hibernate.jdbc.batch_versioned_data true
+
+
+## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default)
+
+#hibernate.jdbc.use_scrollable_resultset true
+
+
+## use streams when writing binary types to / from JDBC
+
+hibernate.jdbc.use_streams_for_binary true
+
+
+## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row
+
+#hibernate.jdbc.use_get_generated_keys false
+
+
+## choose a custom JDBC batcher
+
+# hibernate.jdbc.factory_class
+
+
+## enable JDBC result set column alias caching 
+## (minor performance enhancement for broken JDBC drivers)
+
+# hibernate.jdbc.wrap_result_sets
+
+
+## choose a custom SQL exception converter
+
+#hibernate.jdbc.sql_exception_converter
+
+
+
+##########################
+### Second-level Cache ###
+##########################
+
+## optimize chache for minimal "puts" instead of minimal "gets" (good for clustered cache)
+
+#hibernate.cache.use_minimal_puts true
+
+
+## set a prefix for cache region names
+
+hibernate.cache.region_prefix hibernate.test
+
+
+## disable the second-level cache
+
+#hibernate.cache.use_second_level_cache false
+
+
+## enable the query cache
+
+hibernate.cache.use_query_cache true
+
+
+## store the second-level cache entries in a more human-friendly format
+
+#hibernate.cache.use_structured_entries true
+
+
+## choose a cache implementation
+
+#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
+#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
+hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
+#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
+#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
+#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
+
+
+## choose a custom query cache implementation
+
+#hibernate.cache.query_cache_factory
+
+
+
+############
+### JNDI ###
+############
+
+## specify a JNDI name for the SessionFactory
+
+#hibernate.session_factory_name hibernate/session_factory
+
+
+## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction;
+## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which
+## is the best approach in an application server
+
+#file system
+#hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory
+#hibernate.jndi.url file:/
+
+#WebSphere
+#hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory
+#hibernate.jndi.url iiop://localhost:900/
+

Added: trunk/HibernateExt/shards/etc/log4j.properties
===================================================================
--- trunk/HibernateExt/shards/etc/log4j.properties	                        (rev 0)
+++ trunk/HibernateExt/shards/etc/log4j.properties	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+### direct log messages to stdout ###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### direct messages to file hibernate.log ###
+#log4j.appender.file=org.apache.log4j.FileAppender
+#log4j.appender.file.File=hibernate.log
+#log4j.appender.file.layout=org.apache.log4j.PatternLayout
+#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### set log levels - for more verbose logging change 'info' to 'debug' ###
+
+log4j.rootLogger=warn, stdout
+
+log4j.logger.org.hibernate=info
+
+
+### log just the SQL
+log4j.logger.org.hibernate.SQL=debug
+
+#log4j.logger.org.hibernate.engine.CascadingAction=debug
+
+### log JDBC bind parameters ###
+#log4j.logger.org.hibernate.type=debug
+
+### log schema export/update ###
+log4j.logger.org.hibernate.tool.hbm2ddl=debug
+
+### log cache activity ###
+#log4j.logger.org.hibernate.cache=debug
+
+### enable the following line if you want to track down connection ###
+### leakages when using DriverManagerConnectionProvider ###
+#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
+
+### annotation logs
+#log4j.logger.org.hibernate.annotation=info
+#log4j.logger.org.hibernate.cfg=info
+#log4j.logger.org.hibernate.cfg.SettingsFactory=info
+#log4j.logger.org.hibernate.cfg.AnnotationBinder=info
+#log4j.logger.org.hibernate.cfg.AnnotationConfiguration=info
+#log4j.logger.org.hibernate.cfg.Ejb3Column=info
\ No newline at end of file

Added: trunk/HibernateExt/shards/jdbc/hsqldb.jar
===================================================================
(Binary files differ)


Property changes on: trunk/HibernateExt/shards/jdbc/hsqldb.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/HibernateExt/shards/jdbc/mysql-3.0.14.jar
===================================================================
(Binary files differ)


Property changes on: trunk/HibernateExt/shards/jdbc/mysql-3.0.14.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/HibernateExt/shards/lgpl.txt
===================================================================
--- trunk/HibernateExt/shards/lgpl.txt	                        (rev 0)
+++ trunk/HibernateExt/shards/lgpl.txt	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+		     
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+

Added: trunk/HibernateExt/shards/lib/README.txt
===================================================================
--- trunk/HibernateExt/shards/lib/README.txt	                        (rev 0)
+++ trunk/HibernateExt/shards/lib/README.txt	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,11 @@
+Hibernate Shards dependencies
+=============================
+
+Core
+====
+hibernate core dependencies: required (see Hibernate Core for more information)
+#list all other dependencies (including version) and put the jar in ./lib
+
+Test
+====
+#If needed list test dependencies
\ No newline at end of file

Added: trunk/HibernateExt/shards/readme.txt
===================================================================
--- trunk/HibernateExt/shards/readme.txt	                        (rev 0)
+++ trunk/HibernateExt/shards/readme.txt	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+Hibernate Shards
+================
+Version: 3.0.0.BETA1, 20.03.2007
+
+Description
+-----------
+
+You can't always put all your relational data in a single relational database.
+Sometimes you simply have too much data. Sometimes you have a distributed deployment architecture
+(network latency between California and India might be too high to have a single database). There might
+even be non-technical reasons (a potential customer simply won't do the deal unless her company's data lives in its
+own db instance). Whatever your reasons, talking to multiple relational databases inevitably complicates
+the development of your application. Hibernate Shards is a framework that is designed to encapsulate and
+reduce this complexity by adding support for horizontal partitioning on top of Hibernate Core. Simply put, 
+we aim to provide a unified view of multiple databases via Hibernate.
+
+Instructions
+------------
+
+Unzip to installation directory, read doc/reference
+
+
+Contact
+------------
+
+Latest Documentation:
+
+   http://hibernate.org
+
+Bug Reports:
+
+   Hibernate JIRA (preferred)
+   hibernate-devel at lists.sourceforge.net
+
+Free Technical Support:
+
+   http://forum.hibernate.org
+
+
+Notes
+-----------
+
+If you want to contribute, go to http://www.hibernate.org/
+
+This software and its documentation are distributed under the terms of the
+FSF Lesser Gnu Public License (see lgpl.txt).
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/BaseHasShardIdList.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/BaseHasShardIdList.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/BaseHasShardIdList.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * Base implementation for HasShadIdList.
+ * Takes care of null/empty checks.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseHasShardIdList implements HasShardIdList {
+
+  // our list of {@link ShardId} objects
+  protected final List<ShardId> shardIds;
+
+  /**
+   * Construct a BaseHasShardIdList.  {@link List} cannot be empty
+   * @param shardIds  the {@link ShardId}s
+   */
+  protected BaseHasShardIdList(List<ShardId> shardIds) {
+    Preconditions.checkNotNull(shardIds);
+    Preconditions.checkArgument(!shardIds.isEmpty());
+    // make our own copy to be safe
+    this.shardIds = new ArrayList<ShardId>(shardIds);
+  }
+
+  public List<ShardId> getShardIds() {
+    return Collections.unmodifiableList(shardIds);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/CrossShardAssociationException.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/CrossShardAssociationException.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/CrossShardAssociationException.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.HibernateException;
+
+/**
+ * Exception thrown when someone attempts to create a cross-shard association.
+ * Here's an example of a cross-shard association.  Let's say we have
+ * AccountManager and Account.  There is an owned, one-to-many relationship
+ * between AccountManagers and Accounts, and we are sharding by AccountManager.
+ * That means an AccountManager and all her Accounts live on the same shard.
+ * Now suppose you did the following:
+ *
+ * {@code
+public void reassignLeastProfitableAccount(AccountManager mgr1, AccountManager mgr2) {
+  Account acct = mgr1.removeLeastProfitableAccount();
+  acct.setAccountManager(mgr2);
+  mgr2.addAccount(acct);
+}}
+ * If the 2 managers happen to live on different shards and you were to then
+ * attempt to save the second manager you would receive a
+ * CrossShardAssociationException because the account lives on a different shard
+ * than the manager with which you're attempting to associate it.
+ *
+ * Now you'll notice a few things about this example.  First, it doesn't really
+ * respect the constraints of an owned one-to-many relationship.  If AccountManagers
+ * truly own Accounts (as opposed to just being associated with them), it doesn't
+ * makes sense to reassign an account because the AccountManager is part of that
+ * object's identity.  And If the relationship is an association then you
+ * probably shouldn't be using Hibernate Sharding to manage this relationship
+ * because Accounts are going to pass between AccountManagers, which means
+ * Accounts are going to need to pass between shards, which means you're better
+ * off just letting Hibernate manage the relationship between AccountManagers
+ * and account ids and loading the objects uniquely identified by those ids
+ * on your own.
+ *
+ * The other thing you'll notice is that if the two managers happen to live on
+ * the same shard this will work just fine.  Yup, it will.  We can detect
+ * cross-shard relationships.  We can't detect risky code.  You just need to
+ * be careful here.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class CrossShardAssociationException extends HibernateException {
+
+  public CrossShardAssociationException(Throwable root) {
+    super(root);
+  }
+
+  public CrossShardAssociationException(String string, Throwable root) {
+    super(string, root);
+  }
+
+  public CrossShardAssociationException(String s) {
+    super(s);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/HasShardIdList.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/HasShardIdList.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/HasShardIdList.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import java.util.List;
+
+/**
+ * Interface for objects that can provide a List of ShardIds. 
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface HasShardIdList {
+
+  /**
+   * @return an unmodifiable list of {@link ShardId}s
+   */
+  List<ShardId> getShardIds();
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/Shard.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/Shard.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/Shard.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,191 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.criteria.CriteriaEvent;
+import org.hibernate.shards.criteria.CriteriaId;
+import org.hibernate.shards.criteria.ShardedCriteria;
+import org.hibernate.shards.query.QueryEvent;
+import org.hibernate.shards.query.QueryId;
+import org.hibernate.shards.query.ShardedQuery;
+import org.hibernate.shards.session.OpenSessionEvent;
+
+import org.hibernate.Criteria;
+import org.hibernate.LockMode;
+import org.hibernate.Query;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Interface representing a Shard.  A shard is a physical partition (as opposed
+ * to a virtual partition).  Shards know how to lazily instantiate Sessions
+ * and apply {@link OpenSessionEvent}s, {@link CriteriaEvent}s, and {@link QueryEvent}s.
+ * Anybody else have a nagging suspicion this can get folded into the Session
+ * itself?
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface Shard {
+
+  /**
+   * @return the SessionFactoryImplementor that owns the Session associated with this Shard
+   */
+  SessionFactoryImplementor getSessionFactoryImplementor();
+
+  /**
+   * @return the Session associated with this Shard.  Will return null if
+   * the Session has not yet been established.
+   */
+  /* @Nullable */ Session getSession();
+
+  /**
+   * @param event the event to add
+   */
+  void addOpenSessionEvent(OpenSessionEvent event);
+
+  /**
+   * @return establish a Session using the SessionFactoryImplementor associated
+   * with this Shard and apply any OpenSessionEvents that have been added.  If
+   * the Session has already been established just return it.
+   */
+  Session establishSession();
+
+  /**
+   * @param id the id of the Criteria
+   * @return the Critieria uniquely identified by the given id (unique to the Shard)
+   */
+  Criteria getCriteriaById(CriteriaId id);
+
+  /**
+   * @param id the id of the Criteria with which the event should be associated
+   * @param event the event to add
+   */
+  void addCriteriaEvent(CriteriaId id, CriteriaEvent event);
+
+  /**
+   * @param shardedCriteria  the ShardedCriteria for which this Shard should
+   * create an actual {@link Criteria} object.
+   * @return a Criteria for the given ShardedCriteria
+   */
+  Criteria establishCriteria(ShardedCriteria shardedCriteria);
+
+  /**
+   * @see Session#get(Class, Serializable)
+   */
+  Object get(Class<?> clazz, Serializable id);
+
+  /**
+   * @see Session#get(Class, Serializable, LockMode)
+   */
+  Object get(Class<?> clazz, Serializable id, LockMode lockMode);
+
+  /**
+   * @see Session#get(String, Serializable)
+   */
+  Object get(String entityName, Serializable id);
+
+  /**
+   * @see Session#get(String, Serializable, LockMode)
+   */
+  Object get(String entityName, Serializable id, LockMode lockMode);
+
+  /**
+   * @see Criteria#list()
+   */
+  List<Object> list(CriteriaId criteriaId);
+
+  /**
+   * @see Criteria#uniqueResult()
+   */
+  Object uniqueResult(CriteriaId criteriaId);
+
+  /**
+   * @see Session#save(String, Object)
+   */
+  Serializable save(String entityName, Object obj);
+
+  /**
+   * @see Session#saveOrUpdate(Object)
+   */
+  void saveOrUpdate(Object obj);
+
+  /**
+   * @see Session#saveOrUpdate(String, Object)
+   */
+  void saveOrUpdate(String entityName, Object obj);
+
+  /**
+   * @see Session#update(Object)
+   */
+  void update(Object object);
+
+  /**
+   * @see Session#update(String, Object)
+   */
+  void update(String entityName, Object obj);
+
+  /**
+   * @see Session#delete(Object)
+   */
+  void delete(Object object);
+
+  /**
+   * @see Session#delete(String, Object)
+   */
+  void delete(String entityName, Object object);
+
+  /**
+   * @return the ids of the virtual shards that are mapped to this physical shard.
+   * The returned Set is unmodifiable.
+   */
+  Set<ShardId> getShardIds();
+
+  /**
+   * @param queryId the id of the Query
+   * @return the Query uniquely identified by the given id (unique to the Shard)
+   */
+  Query getQueryById(QueryId queryId);
+
+  /**
+   * @param id the id of the Query with which the event should be associated
+   * @param event the event to add
+   */
+  void addQueryEvent(QueryId id, QueryEvent event);
+
+  /**
+   * @param shardedQuery  the ShardedQuery for which this Shard should
+   * create an actual {@link Query} object.
+   * @return a Query for the given ShardedQuery
+   */
+  Query establishQuery(ShardedQuery shardedQuery);
+
+  /**
+   * @see Query#list()
+   */
+  List<Object> list(QueryId queryId);
+
+  /**
+   * @see Query#uniqueResult()
+   */
+  Object uniqueResult(QueryId queryId);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardId.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardId.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardId.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+/**
+ * Uniquely identifies a virtual shard.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardId {
+
+  private final int shardId;
+
+  public ShardId(int shardId) {
+    this.shardId = shardId;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final ShardId shardId1 = (ShardId)o;
+
+    return shardId == shardId1.shardId;
+  }
+
+  @Override
+  public int hashCode() {
+    return shardId;
+  }
+
+  public int getId() {
+    return shardId;
+  }
+
+  @Override
+  public String toString() {
+    return Integer.toString(shardId);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,386 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.criteria.CriteriaEvent;
+import org.hibernate.shards.criteria.CriteriaId;
+import org.hibernate.shards.criteria.ShardedCriteria;
+import org.hibernate.shards.query.QueryEvent;
+import org.hibernate.shards.query.QueryId;
+import org.hibernate.shards.query.ShardedQuery;
+import org.hibernate.shards.session.OpenSessionEvent;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Preconditions;
+import org.hibernate.shards.util.Sets;
+
+import org.hibernate.Criteria;
+import org.hibernate.Interceptor;
+import org.hibernate.LockMode;
+import org.hibernate.Query;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Concrete implementation of the {@link Shard} interface.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardImpl implements Shard {
+
+  // ids of virtual shards mapped to this physical shard
+  private final Set<ShardId> shardIds;
+
+  // the SessionFactory that owns this Session
+  private final SessionFactoryImplementor sessionFactory;
+
+  // the interceptor to be used when instantiating the Session
+  private final Interceptor interceptor;
+
+  // the Set of shardIds is immutable, so we calculate the hashcode once up
+  // front and hole on to it as an optimization
+  private final int hashCode;
+
+  // the actual Session!  Will be null until someone calls establishSession()
+  private Session session;
+
+  // events that need to fire when the Session is opened
+  private final LinkedList<OpenSessionEvent> openSessionEvents = Lists.newLinkedList();
+
+  // maps criteria ids to Criteria objects for quick lookup
+  private Map<CriteriaId, Criteria> criteriaMap = Maps.newHashMap();
+
+  // maps query ids to Query objects for quick lookup
+  private Map<QueryId, Query> queryMap = Maps.newHashMap();
+
+  // maps criteria ids to lists of criteria events.  The criteria events
+  // need to fire when the actual Criteria is established
+  private Map<CriteriaId, LinkedList<CriteriaEvent>> criteriaEventMap = Maps.newHashMap();
+
+  // maps query ids to lists of query events.  The query events
+  // need to fire when the actual Query is established
+  private Map<QueryId, LinkedList<QueryEvent>> queryEventMap = Maps.newHashMap();
+
+  /**
+   * Construct a ShardImpl
+   * @param shardId the logical shardId that is mapped to this physical shard
+   * @param sessionFactory the SessionFactory that we'll use to create the
+   * Session (if and when we create the Session)
+   */
+  public ShardImpl(
+      ShardId shardId,
+      SessionFactoryImplementor sessionFactory) {
+    this(Collections.singleton(shardId), sessionFactory, null);
+  }
+
+  /**
+   * Construct a ShardImpl
+   * @param shardIds the logical shardIds that are mapped to this physical shard
+   * @param sessionFactory the SessionFactory that we'll use to create the
+   * Session (if and when we create the Session)
+   */
+  public ShardImpl(
+      Set<ShardId> shardIds,
+      SessionFactoryImplementor sessionFactory) {
+    this(shardIds, sessionFactory, null);
+  }
+
+  /**
+   * Construct a ShardImpl
+   * @param shardIds the logical shardIds that are mapped to this physical shard
+   * @param sessionFactory the SessionFactory that we'll use to create the
+   * Session (if and when we create the Session)
+   * @param interceptor the interceptor that we'll pass in when we create the
+   * Session (if and when we create the Session).  Can be null.
+   */
+  public ShardImpl(
+      Set<ShardId> shardIds,
+      SessionFactoryImplementor sessionFactory,
+      /*@Nullable*/ Interceptor interceptor) {
+    // make a copy to be safe
+    this.shardIds = Collections.unmodifiableSet(Sets.newHashSet(shardIds));
+    this.hashCode = shardIds.hashCode();
+    this.sessionFactory = sessionFactory;
+    this.interceptor = interceptor;
+  }
+
+  public SessionFactoryImplementor getSessionFactoryImplementor() {
+    return sessionFactory;
+  }
+
+  public Session getSession() {
+    return session;
+  }
+
+  public void addOpenSessionEvent(OpenSessionEvent event) {
+    Preconditions.checkNotNull(event);
+    openSessionEvents.addLast(event);
+  }
+
+  public Session establishSession() {
+    // if we already have a session we just return it
+    if (session == null) {
+      // make sure we use the provided interceptor when we open the session
+      if(interceptor == null) {
+        session = sessionFactory.openSession();
+      } else {
+        session = sessionFactory.openSession(interceptor);
+      }
+      // apply any OpenSessionEvents that have been queued up.
+      if (openSessionEvents != null) {
+        for (OpenSessionEvent event : openSessionEvents) {
+          event.onOpenSession(session);
+        }
+        // clear the list so they can't get fired again
+        openSessionEvents.clear();
+      }
+    }
+    return session;
+  }
+
+  public Criteria getCriteriaById(CriteriaId id) {
+    return criteriaMap.get(id);
+  }
+
+  public void addCriteriaEvent(CriteriaId id, CriteriaEvent event) {
+    addEventToMap(criteriaEventMap, id, event);
+  }
+
+  public Criteria establishCriteria(ShardedCriteria shardedCriteria) {
+    CriteriaId critId = shardedCriteria.getCriteriaId();
+    Criteria crit = criteriaMap.get(critId);
+    // if the Criteria has already been established we just return it
+    if (crit == null) {
+      // Criteria does not yet exist so need to create it
+      crit = shardedCriteria.getCriteriaFactory().createCriteria(establishSession());
+       // add it to the map right away in case some of our events require it
+      criteriaMap.put(critId, crit);
+      // see if we have events that we need to apply to the Criteria
+      List<CriteriaEvent> events = criteriaEventMap.get(critId);
+      if (events != null) {
+        // we've got events, fire away
+        for (CriteriaEvent event : events) {
+          event.onEvent(crit);
+        }
+        // clear the list so they can't get fired again
+        events.clear();
+      }
+    }
+    return crit;
+  }
+
+  public Query getQueryById(QueryId id) {
+    return queryMap.get(id);
+  }
+
+  public void addQueryEvent(QueryId id, QueryEvent event) {
+    addEventToMap(queryEventMap, id, event);
+  }
+
+  public Query establishQuery(ShardedQuery shardedQuery) {
+    QueryId queryId = shardedQuery.getQueryId();
+    Query query = queryMap.get(queryId);
+    if(query == null) {
+      // Criteria does not yet exist so need to create it
+      query = shardedQuery.getQueryFactory().createQuery(establishSession());
+       // add it to the map right away in case some of our events require it
+      queryMap.put(queryId, query);
+      // see if we have events that we need to apply to the Query
+      List<QueryEvent> events = queryEventMap.get(queryId);
+      if(events != null) {
+        // we've got events, fire away
+        for(QueryEvent event : events) {
+          event.onEvent(query);
+        }
+        // clear the list so they can't get fired again
+        events.clear();
+      }
+    }
+    return query;
+  }
+
+  /**
+   * Equality is defined using the list of virtual shard ids that are mapped
+   * to this physical shard.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof ShardImpl)) {
+      return false;
+    }
+
+    final ShardImpl shard = (ShardImpl)o;
+
+    if (!shardIds.equals(shard.shardIds)) {
+      return false;
+    }
+    return false;
+
+  }
+
+  @Override
+  public int hashCode() {
+    // use the cached value
+    return hashCode;
+  }
+
+  public Object get(Class<?> clazz, Serializable id) {
+    return establishSession().get(clazz, id);
+  }
+
+  public Object get(Class<?> clazz, Serializable id, LockMode lockMode) {
+    return establishSession().get(clazz, id, lockMode);
+  }
+
+  public Object get(String entityName, Serializable id) {
+    return establishSession().get(entityName, id);
+  }
+
+  public Object get(String entityName, Serializable id, LockMode lockMode) {
+    return establishSession().get(entityName, id, lockMode);
+  }
+
+  @SuppressWarnings("unchecked")
+  public List<Object> list(CriteriaId criteriaId) {
+    return criteriaMap.get(criteriaId).list();
+  }
+
+  public Object uniqueResult(CriteriaId criteriaId) {
+    return criteriaMap.get(criteriaId).uniqueResult();
+  }
+
+  @SuppressWarnings("unchecked")
+  public List<Object> list(QueryId queryId) {
+    return queryMap.get(queryId).list();
+  }
+
+  public Object uniqueResult(QueryId queryId) {
+    return queryMap.get(queryId).uniqueResult();
+  }
+
+  public Set<ShardId> getShardIds() {
+    return shardIds;
+  }
+
+  /**
+   * @return the OpenSessionEvents that are waiting to fire
+   */
+  LinkedList<OpenSessionEvent> getOpenSessionEvents() {
+    return openSessionEvents;
+  }
+
+  /**
+   * @return the map from CriteriaId to Criteria
+   */
+  Map<CriteriaId, Criteria> getCriteriaMap() {
+    return criteriaMap;
+  }
+
+  /**
+   * @return the CrtieriaEvents that are waiting to fire
+   */
+  Map<CriteriaId, LinkedList<CriteriaEvent>> getCriteriaEventMap() {
+    return criteriaEventMap;
+  }
+
+  public Serializable save(String entityName, Object obj) {
+    return establishSession().save(entityName, obj);
+  }
+
+  public void saveOrUpdate(Object obj) {
+    establishSession().saveOrUpdate(obj);
+  }
+
+  public void saveOrUpdate(String entityName, Object obj) {
+    establishSession().saveOrUpdate(entityName, obj);
+  }
+
+  public void update(Object object) {
+    establishSession().update(object);
+  }
+
+  public void update(String entityName, Object obj) {
+    establishSession().update(entityName, obj);
+  }
+
+  public void delete(Object object) {
+    establishSession().delete(object);
+  }
+
+  public void delete(String entityName, Object object) {
+    establishSession().delete(entityName, object);
+  }
+
+  @Override
+  public String toString() {
+    return getSessionFactoryImplementor().getSettings().getSessionFactoryName();
+  }
+
+  /**
+   * @return the map from QueryId to Query
+   */
+  Map<QueryId, Query> getQueryMap() {
+    return queryMap;
+  }
+
+  /**
+   * @return the QueryEvents that are waiting to fire
+   */
+  Map<QueryId, LinkedList<QueryEvent>> getQueryEventMap() {
+    return queryEventMap;
+  }
+
+  /**
+   * @return the Interceptor we use in the construction of the Session (if
+   * and when we construct the Session).  Can be null.
+   */
+  public /*@Nullable*/ Interceptor getInterceptor() {
+    return interceptor;
+  }
+
+  /**
+   * Utility function for adding events to maps where the key is an id and the
+   * value is a linked list of events.
+   */
+  private static <D, E> void addEventToMap(Map<D, LinkedList<E>> map, D id, E event) {
+    Preconditions.checkNotNull(id);
+    Preconditions.checkNotNull(event);
+    // see if we already have an event list for this query
+    LinkedList<E> events = map.get(id);
+    if (events == null) {
+      // no list yet, so create it
+      events = Lists.newLinkedList();
+      map.put(id, events);
+    }
+    // always add events to the end
+    events.addLast(event);
+  }
+
+}
+

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+/**
+ * Simple interface used to reference something we can do against a {@link Shard}.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public interface ShardOperation<T> {
+
+  /**
+   * @param shard the shard to execute against
+   * @return the result of the operation
+   */
+  T execute(Shard shard);
+
+  /**
+   * @return the name of the operation (useful for logging and debugging)
+   */
+  String getOperationName();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedConfiguration.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedConfiguration.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedConfiguration.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,272 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.cfg.ShardedEnvironment;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.session.ShardedSessionFactoryImpl;
+import org.hibernate.shards.session.ShardedSessionFactory;
+import org.hibernate.shards.util.Preconditions;
+import org.hibernate.shards.util.Sets;
+import org.hibernate.shards.util.Maps;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.mapping.OneToOne;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.mapping.Property;
+import org.hibernate.util.PropertiesHelper;
+import org.hibernate.SessionFactory;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Like regular Hibernate's Configuration, this class helps construct your
+ * factories. Not extending Hibernate's Configuration because that is the one place
+ * where the notion of a single database is specified (i.e. in the
+ * hibernate.properties file). While we would like to maintain the Hibernate paradigm
+ * as much as possible, this is one place it might be different.
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ShardedConfiguration {
+
+  // the prototype config that we'll use when constructing the shard-specific
+  // configs
+  private final Configuration prototypeConfiguration;
+
+  // shard-specific configs
+  private final List<Configuration> configurations;
+
+  // user-defined sharding behavior
+  private final ShardStrategyFactory shardStrategyFactory;
+
+  // maps virtual shard ids to physical shard ids
+  private final Map<Integer, Integer> virtualShardToShardMap;
+
+  // maps physical shard ids to sets of virtual shard ids
+  private final Map<Integer, Set<ShardId>> shardToVirtualShardIdMap;
+
+  // our lovely logger
+  private final Log log = LogFactory.getLog(getClass());
+
+  // constant used in config files to specify the shard id
+  static final String SHARD_ID_PROPERTY = "hibernate.connection.shard_id";
+
+  // the properties that we let users vary across shards.  if the property
+  // isn't in this list we'll take the value from the prototype config
+  static final Set<String> VARIABLE_PROPERTIES = Sets.newHashSet(
+      Environment.URL,
+      Environment.USER,
+      Environment.PASS,
+      Environment.SESSION_FACTORY_NAME,
+      SHARD_ID_PROPERTY);
+
+  /**
+   * Constructs a ShardedConfiguration.
+   *
+   * @param prototypeConfiguration The prototype for all configurations that
+   * will be used to create the {@link SessionFactory} objects
+   * that are internal to the {@link ShardedSessionFactory}.
+   * Every {@link SessionFactory} within the
+   * {@link ShardedSessionFactory} objects created by the ShardedConfiguration
+   * will look the same, except for its values that correspond to
+   * Configuration properties that we consider to be "variable" (they can
+   * vary from shard to shard).  These properties are:
+   * {@link Environment#URL}
+   * {@link Environment#USER}
+   * {@link Environment#PASS}
+   * {@link Environment#SESSION_FACTORY_NAME}
+   * Unlike the {@link Configuration} instances contained in the configurations
+   * param, this {@link Configuration} needs to have all of its mappings.
+   *
+   * @param configurations The shard-specific {@link Configuration}s
+   * @param shardStrategyFactory factory that knows how to create the right type of shard strategy
+   */
+  public ShardedConfiguration(
+      Configuration prototypeConfiguration,
+      List<Configuration> configurations,
+      ShardStrategyFactory shardStrategyFactory) {
+    this(prototypeConfiguration, configurations, shardStrategyFactory, Maps.<Integer, Integer>newHashMap());
+  }
+
+  /**
+   * Constructs a ShardedConfiguration.
+   *
+   * @param prototypeConfiguration The prototype for all configurations that
+   * will be used to create the {@link org.hibernate.SessionFactory} objects
+   * that are internal to the {@link org.hibernate.shards.session.ShardedSessionFactory}.
+   * Every {@link org.hibernate.SessionFactory} within the
+   * {@link org.hibernate.shards.session.ShardedSessionFactory} objects created by the ShardedConfiguration
+   * will look the same, except for its values that correspond to
+   * Configuration properties that we consider to be "variable" (they can
+   * vary from shard to shard).  These properties are:
+   * {@link org.hibernate.cfg.Environment#URL}
+   * {@link org.hibernate.cfg.Environment#USER}
+   * {@link org.hibernate.cfg.Environment#PASS}
+   * {@link org.hibernate.cfg.Environment#SESSION_FACTORY_NAME}
+   * Unlike the {@link org.hibernate.cfg.Configuration} instances contained in the configurations
+   * param, this {@link org.hibernate.cfg.Configuration} needs to have all of its mappings.
+   *@param configurations Cannot be empty.
+   * @param shardStrategyFactory factory that knows how to create the right kind of shard strategy
+   * @param virtualShardToShardMap A map that maps virtual shard ids to real
+   */
+  public ShardedConfiguration(
+      Configuration prototypeConfiguration,
+      List<Configuration> configurations,
+      ShardStrategyFactory shardStrategyFactory,
+      Map<Integer, Integer> virtualShardToShardMap) {
+    Preconditions.checkNotNull(prototypeConfiguration);
+    Preconditions.checkNotNull(configurations);
+    Preconditions.checkArgument(!configurations.isEmpty());
+    Preconditions.checkNotNull(shardStrategyFactory);
+    Preconditions.checkNotNull(virtualShardToShardMap);
+
+    this.prototypeConfiguration = prototypeConfiguration;
+    this.configurations = configurations;
+    this.shardStrategyFactory = shardStrategyFactory;
+    this.virtualShardToShardMap = virtualShardToShardMap;
+    if (!virtualShardToShardMap.isEmpty()) {
+      // build the map from shard to set of virtual shards
+      shardToVirtualShardIdMap = Maps.newHashMap();
+      for(Map.Entry<Integer, Integer> entry : virtualShardToShardMap.entrySet()) {
+        Set<ShardId> set = shardToVirtualShardIdMap.get(entry.getValue());
+        // see if we already have a set of virtual shards
+        if (set == null) {
+          // we don't, so create it and add it to the map
+          set = Sets.newHashSet();
+          shardToVirtualShardIdMap.put(entry.getValue(), set);
+        }
+        set.add(new ShardId(entry.getKey()));
+      }
+    } else {
+      shardToVirtualShardIdMap = Maps.newHashMap();
+    }
+  }
+
+  /**
+   * @return A ShardedSessionFactory built from the prototype config and
+   * the shard-specific configs passed into the constructor.
+   */
+  public ShardedSessionFactory buildShardedSessionFactory() {
+    Map<SessionFactoryImplementor, Set<ShardId>> sessionFactories = Maps.newHashMap();
+    // since all configs get their mappings from the prototype config, and we
+    // get the set of classes that don't support top-level saves from the mappings,
+    // we can get the set from the prototype and then just reuse it.
+    Set<Class<?>> classesWithoutTopLevelSaveSupport =
+        determineClassesWithoutTopLevelSaveSupport(prototypeConfiguration);
+    for (Configuration config : configurations) {
+      populatePrototypeWithVariableProperties(config);
+      // get the shardId from the shard-specific config
+      Integer shardId = Integer.parseInt(config.getProperty(SHARD_ID_PROPERTY));
+      Set<ShardId> virtualShardIds;
+      if (virtualShardToShardMap.isEmpty()) {
+        // simple case, virtual and physical are the same
+        virtualShardIds = Collections.singleton(new ShardId(shardId));
+      } else {
+        // get the set of shard ids that are mapped to the physical shard
+        // described by this config
+        virtualShardIds = shardToVirtualShardIdMap.get(shardId);
+      }
+      sessionFactories.put(buildSessionFactory(), virtualShardIds);
+    }
+    final boolean doFullCrossShardRelationshipChecking =
+        PropertiesHelper.getBoolean(
+            ShardedEnvironment.CHECK_ALL_ASSOCIATED_OBJECTS_FOR_DIFFERENT_SHARDS,
+            prototypeConfiguration.getProperties(),
+            true);
+    return
+        new ShardedSessionFactoryImpl(
+            sessionFactories,
+            shardStrategyFactory,
+            classesWithoutTopLevelSaveSupport,
+            doFullCrossShardRelationshipChecking);
+  }
+
+  /**
+   * @return the Set of mapped classes that don't support top level saves
+   */
+  @SuppressWarnings("unchecked")
+  private Set<Class<?>> determineClassesWithoutTopLevelSaveSupport(Configuration config) {
+    Set<Class<?>> classesWithoutTopLevelSaveSupport = Sets.newHashSet();
+    for(Iterator<PersistentClass> pcIter = config.getClassMappings(); pcIter.hasNext(); ) {
+      PersistentClass pc = pcIter.next();
+      for(Iterator<Property> propIter = pc.getPropertyIterator(); propIter.hasNext(); ) {
+        if(doesNotSupportTopLevelSave(propIter.next())) {
+          Class<?> mappedClass = pc.getMappedClass();
+          log.info(String.format("Class %s does not support top-level saves.", mappedClass.getName()));
+          classesWithoutTopLevelSaveSupport.add(mappedClass);
+          break;
+        }
+      }
+    }
+    return classesWithoutTopLevelSaveSupport;
+  }
+
+  /**
+   * there may be other scenarios, but mappings that contain one-to-one mappings
+   * definitely can't be saved as top-level objects (not part of a cascade and
+   * no properties from which the shard can be inferred)
+   */
+  boolean doesNotSupportTopLevelSave(Property property) {
+    return property.getValue() != null &&
+        OneToOne.class.isAssignableFrom(property.getValue().getClass());
+  }
+
+  /**
+   * Takes the values of the properties declared in VARIABLE_PROPERTIES from
+   * a shard-specific config and sets them as the values of the same properties
+   * in the prototype config.
+   */
+  void populatePrototypeWithVariableProperties(Configuration config) {
+    copyVariableProperties(prototypeConfiguration, config);
+  }
+
+  /**
+   * Helper function to copy variable properties from the shard-specific config
+   * to the prototype config
+   */
+  static void copyVariableProperties(Configuration prototype, Configuration config) {
+    for(String property : VARIABLE_PROPERTIES) {
+      copyPropertyToPrototype(prototype, config, property);
+    }
+  }
+
+  /**
+   * Helper function to copy one variable property from the shard-specific config
+   * to the prototype config
+   */
+  static void copyPropertyToPrototype(Configuration prototype, Configuration config, String property) {
+    prototype.setProperty(property, config.getProperty(property));
+  }
+
+  /**
+   * Helper function that creates an actual SessionFactory.
+   */
+  private SessionFactoryImplementor buildSessionFactory() {
+    return (SessionFactoryImplementor) prototypeConfiguration.buildSessionFactory();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedTransaction.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedTransaction.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/ShardedTransaction.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.Transaction;
+import org.hibernate.Session;
+
+/**
+ * Simple interface to represent a shard-aware {@link Transaction}.
+ *
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public interface ShardedTransaction extends Transaction {
+
+  /**
+   * If a new Session is opened while ShardedTransaction exists, this method is
+   * called with the Session as argument. Implementations should set up a
+   * transaction for this session and sync it with ShardedTransaction
+   *
+   * @param session the Session on which the Transaction should be setup
+   */
+  void setupTransaction(Session session);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/cfg/ShardedEnvironment.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/cfg/ShardedEnvironment.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/cfg/ShardedEnvironment.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.cfg;
+
+import org.hibernate.cfg.Environment;
+
+/**
+ * Hibernate Shards configuration properties.
+ * @see Environment
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public final class ShardedEnvironment {
+
+  /**
+   * Configuration property that determines whether or not we examine all
+   * associated objects for shard conflicts when we save or update.  A shard
+   * conflict is when we attempt to associate one object that lives on shard X
+   * with an object that lives on shard Y.  Turning this on will hurt
+   * performance but will prevent the programmer from ending up with the
+   * same entity on multiple shards, which is bad (at least in the current version). 
+   */
+  public static final String CHECK_ALL_ASSOCIATED_OBJECTS_FOR_DIFFERENT_SHARDS = "hibernate.shard.check_all_associated_objects_for_different_shards";
+
+  private ShardedEnvironment() {}
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddCriterionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddCriterionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddCriterionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Criterion;
+
+/**
+ * Event that allows a Criterion to be lazily added to a Criteria.
+ * @see Criteria#add(Criterion) 
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class AddCriterionEvent implements CriteriaEvent {
+
+  // the Criterion we're going to add when the event fires
+  private final Criterion criterion;
+
+  public AddCriterionEvent(Criterion criterion) {
+    this.criterion = criterion;
+  }
+
+
+  public void onEvent(Criteria crit) {
+    crit.add(criterion);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddOrderEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddOrderEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/AddOrderEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.criterion.Order;
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows an Order to be lazily added to a Criteria.
+ * @see Criteria#addOrder(Order)
+ * 
+ * @author Max Ross <maxr at google.com>
+ */
+class AddOrderEvent implements CriteriaEvent {
+
+  // the Order we're going to add when the event fires
+  private final Order order;
+
+  /**
+   * Construct an AddOrderEvent
+   *
+   * @param order the Order we'll add when the event fires
+   */
+  public AddOrderEvent(Order order) {
+    this.order = order;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.addOrder(order);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateAliasEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateAliasEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateAliasEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows an alias to be lazily added to a Criteria.
+ * @see Criteria#createAlias(String, String)
+ * @see Criteria#createAlias(String, String, int)
+ * @see Criteria#createAlias(String, String, int) 
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class CreateAliasEvent implements CriteriaEvent {
+
+  private enum MethodSig {
+    ASSOC_PATH_AND_ALIAS,
+    ASSOC_PATH_AND_ALIAS_AND_JOIN_TYPE
+  }
+
+  // the signature of the createAlias method we're going to invoke when
+  // the event fires
+  private final MethodSig methodSig;
+
+  // the association path
+  private final String associationPath;
+
+  // the name of the alias we're creating
+  private final String alias;
+
+  // the join type - we look at method sig to see if we should use it
+  private final Integer joinType;
+
+  /**
+   * Construct a CreateAliasEvent
+   *
+   * @param methodSig the signature of the createAlias method we're going to invoke
+   * when the event fires
+   * @param associationPath the association path of the alias we're creating.
+   * @param alias the name of the alias we're creating.
+   * @param joinType the join type of the alias we're creating.  Can be null.
+   */
+  private CreateAliasEvent(
+      MethodSig methodSig,
+      String associationPath,
+      String alias,
+      /*@Nullable*/Integer joinType) {
+    this.methodSig = methodSig;
+    this.associationPath = associationPath;
+    this.alias = alias;
+    this.joinType = joinType;
+  }
+
+  /**
+   * Construct a CreateAliasEvent
+   *
+   * @param associationPath the association path of the alias we're creating.
+   * @param alias the name of the alias we're creating.
+   */
+  public CreateAliasEvent(String associationPath, String alias) {
+    this(MethodSig.ASSOC_PATH_AND_ALIAS, associationPath, alias, null);
+  }
+
+  /**
+   * Construct a CreateAliasEvent
+   *
+   * @param associationPath the association path of the alias we're creating.
+   * @param alias the name of the alias we're creating.
+   * @param joinType the join type of the alias we're creating.
+   */
+  public CreateAliasEvent(String associationPath, String alias, int joinType) {
+    this(MethodSig.ASSOC_PATH_AND_ALIAS_AND_JOIN_TYPE, associationPath, alias,
+        joinType);
+  }
+
+  public void onEvent(Criteria crit) {
+    switch (methodSig) {
+      case ASSOC_PATH_AND_ALIAS:
+        crit.createAlias(associationPath, alias);
+        break;
+      case ASSOC_PATH_AND_ALIAS_AND_JOIN_TYPE:
+        crit.createAlias(associationPath, alias, joinType);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in CreateAliasEvent: " + methodSig);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateSubcriteriaEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateSubcriteriaEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CreateSubcriteriaEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows a Subcriteria to be lazily added to a Criteria.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class CreateSubcriteriaEvent implements CriteriaEvent {
+
+  private final SubcriteriaFactory subcriteriaFactory;
+  private final ShardedSubcriteriaImpl.SubcriteriaRegistrar subcriteriaRegistrar;
+
+  public CreateSubcriteriaEvent(SubcriteriaFactory subcriteriaFactory, ShardedSubcriteriaImpl.SubcriteriaRegistrar subcriteriaRegistrar) {
+    this.subcriteriaFactory = subcriteriaFactory;
+    this.subcriteriaRegistrar = subcriteriaRegistrar;
+  }
+
+  public void onEvent(Criteria crit) {
+    subcriteriaRegistrar.establishSubcriteria(crit, subcriteriaFactory);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Interface for events that can be laziliy applied to a
+ * {@link org.hibernate.Criteria}. Useful because we don't allocate a
+ * {@link org.hibernate.Criteria} until we actually need it, and programmers
+ * might be calling a variety of methods against the
+ * {@link org.hibernate.shards.criteria.ShardedCriteria}
+ * which need to be applied to the actual {@link org.hibernate.Criteria} once
+ * the actual {@link org.hibernate.Criteria} when it is allocated.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface CriteriaEvent {
+
+  /**
+   * Apply the event
+   * @param crit the Criteria to apply the event to
+   */
+  void onEvent(Criteria crit);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+
+/**
+ * Factory that knows how to create a {@link Criteria} for a given {@link Session}
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface CriteriaFactory {
+
+  /**
+   * Create a {@link Criteria} for the given {@link Session}
+   *
+   * @param session the {@link Session}  to be used when creating the {@link Criteria}
+   * @return a {@link Criteria} associated with the given {@link Session}
+   */
+  Criteria createCriteria(Session session);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,135 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+
+/**
+ * Implementation of the {@link CriteriaFactory} interface.
+ * @see Session#createCriteria(Class)
+ * @see Session#createCriteria(Class, String)
+ * @see Session#createCriteria(String)
+ * @see Session#createCriteria(String, String)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaFactoryImpl implements CriteriaFactory {
+
+  private enum MethodSig {
+    CLASS,
+    CLASS_AND_ALIAS,
+    ENTITY,
+    ENTITY_AND_ALIAS
+  }
+
+  // the signature of the createCriteria method we're going to invoke when
+  // the event fires
+  private final MethodSig methodSig;
+
+  // the Class we'll use when we create the Criteria.  We look at methodSig to
+  // see if we should use it.
+  private final Class persistentClass;
+
+  // the alias we'll use when we create the Criteria.  We look at methodSig to
+  // see if we should use it.
+  private final String alias;
+
+  // the entity name we'll use when we create the Criteria.  We look at methodSig to
+  // see if we should use it.
+  private final String entityName;
+
+  /**
+   * Create a CriteriaFactoryImpl
+   *
+   * @param methodSig the signature of the createCriteria method we'll invoke
+   * when the event fires.
+   * @param persistentClass the {@link Class} of the {@link Criteria} we're creating.
+   * Can be null.
+   * @param alias the alias of the {@link Criteria} we're creating.  Can be null.
+   * @param entityName the entity name of the {@link} Criteria we're creating.
+   * Can be null.
+   */
+  private CriteriaFactoryImpl(
+      MethodSig methodSig,
+      /*@Nullable*/ Class persistentClass,
+      /*@Nullable*/ String alias,
+      /*@Nullable*/ String entityName) {
+    this.methodSig = methodSig;
+    this.persistentClass = persistentClass;
+    this.alias = alias;
+    this.entityName = entityName;
+  }
+
+  /**
+   * Create a CriteriaFactoryImpl.
+   *
+   * @param persistentClass the {@link Class} of the {@link Criteria} we're creating.
+   */
+  public CriteriaFactoryImpl(Class persistentClass) {
+    this(MethodSig.CLASS, persistentClass, null, null);
+  }
+
+  /**
+   * Create a CriteriaFactoryImpl.
+   *
+   * @param persistentClass the {@link Class} of the {@link Criteria} we're creating.
+   * @param alias the alias of the {@link Criteria} we're creating.
+   */
+  public CriteriaFactoryImpl(Class persistentClass, String alias) {
+    this(MethodSig.CLASS_AND_ALIAS, persistentClass, alias, null);
+  }
+
+  /**
+   * Create a CriteriaFactoryImpl.
+   *
+   * @param entityName the entity name of the {@link Criteria} we're creating.
+   */
+  public CriteriaFactoryImpl(String entityName) {
+    this(MethodSig.ENTITY, null, null, entityName);
+  }
+
+  /**
+   * Create a CriteriaFactoryImpl.
+   *
+   * @param entityName the entity name of the {@link Criteria} we're creating.
+   * @param alias the alias of the {@link Criteria} we're creating.
+   */
+  public CriteriaFactoryImpl(String entityName, String alias) {
+    this(MethodSig.ENTITY_AND_ALIAS, null, alias, entityName);
+  }
+
+  public Criteria createCriteria(Session session) {
+    switch (methodSig) {
+      case CLASS:
+        return session.createCriteria(persistentClass);
+      case CLASS_AND_ALIAS:
+        return session.createCriteria(persistentClass, alias);
+      case ENTITY:
+        return session.createCriteria(entityName);
+      case ENTITY_AND_ALIAS:
+        return session.createCriteria(entityName, alias);
+      default:
+        throw new ShardedSessionException(
+            "Unknown constructor type for criteria creation: " + methodSig);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaId.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaId.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/CriteriaId.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+/**
+ * Uniquely identifies a {@link ShardedCriteria} 
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaId {
+
+  // the actual id
+  private final int id;
+
+  /**
+   * Construct a CriteriaId
+   *
+   * @param id the int representation of the id
+   */
+  public CriteriaId(int id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the int representation
+   */
+  public int getId() {
+    return id;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof CriteriaId)) {
+      return false;
+    }
+
+    final CriteriaId criteriaId = (CriteriaId)o;
+
+    if (id != criteriaId.id) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return id;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,190 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.strategy.exit.DistinctExitOperation;
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+import org.hibernate.shards.strategy.exit.FirstResultExitOperation;
+import org.hibernate.shards.strategy.exit.MaxResultsExitOperation;
+import org.hibernate.shards.strategy.exit.OrderExitOperation;
+import org.hibernate.shards.strategy.exit.ProjectionExitOperationFactory;
+import org.hibernate.shards.util.Lists;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.criterion.AggregateProjection;
+import org.hibernate.criterion.Distinct;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.RowCountProjection;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.util.List;
+
+/**
+ * Implements the ExitOperationsCollector interface for Critierias
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ExitOperationsCriteriaCollector implements ExitOperationsCollector {
+
+  // maximum number of results requested by the client
+  private Integer maxResults = null;
+
+  // index of the first result requested by the client
+  private Integer firstResult = null;
+
+  // Distinct operation applied to the Criteria
+  private Distinct distinct = null;
+
+  // Average Projection operation applied to the Criteria
+  private AggregateProjection avgProjection = null;
+
+  // Aggregate Projecton operation applied to the Criteria
+  private AggregateProjection aggregateProjection = null;
+
+  // Row Count Projection operation applied to the Criteria
+  private RowCountProjection rowCountProjection;
+
+  // The Session Factory Implementor with which the Criteria is associated
+  private SessionFactoryImplementor sessionFactoryImplementor;
+
+  // Order operations applied to the Criteria
+  private List<Order> orders = Lists.newArrayList();
+
+  // Our friendly neighborhood logger
+  private final Log log = LogFactory.getLog(getClass());
+
+  /**
+   * Sets the maximum number of results requested by the client
+   *
+   * @param maxResults maximum number of results requested by the client
+   * @return this
+   */
+  public ExitOperationsCollector setMaxResults(int maxResults) {
+    this.maxResults = maxResults;
+    return this;
+  }
+
+  /**
+   * Sets the index of the first result requested by the client
+   *
+   * @param firstResult index of the first result requested by the client
+   * @return this
+   */
+  public ExitOperationsCollector setFirstResult(int firstResult) {
+    this.firstResult = firstResult;
+    return this;
+  }
+
+  /**
+   * Adds the given projection.
+   *
+   * @param projection the projection to add
+   * @return this
+   */
+  public ExitOperationsCollector addProjection(Projection projection) {
+    if (projection instanceof Distinct) {
+      this.distinct = (Distinct)projection;
+      // TODO(maulik) Distinct doesn't work yet
+      log.error("Distinct is not ready yet");
+      throw new UnsupportedOperationException();
+    } else if(projection instanceof RowCountProjection) {
+      this.rowCountProjection = (RowCountProjection) projection;
+    } else if(projection instanceof AggregateProjection) {
+      if (projection.toString().toLowerCase().startsWith("avg")) {
+        this.avgProjection = (AggregateProjection) projection;
+      } else {
+        this.aggregateProjection = (AggregateProjection) projection;
+      }
+    } else {
+      log.error("Adding an unsupported Projection: " + projection.getClass().getName());
+      throw new UnsupportedOperationException();
+    }
+    return this;
+  }
+
+  /**
+   * Add the given Order
+   *
+   * @param order the order to add
+   * @return this
+   */
+  public ExitOperationsCollector addOrder(Order order) {
+    this.orders.add(order);
+    return this;
+  }
+
+  public List<Object> apply(List<Object> result) {
+    /**
+     * Herein lies the glory
+     *
+     * hibernate has done as much as it can, we're going to have to deal with
+     * the rest in memory.
+     *
+     * The heirarchy of operations is this so far:
+     * Distinct
+     * Order
+     * FirstResult
+     * MaxResult
+     * RowCount
+     * Average
+     * Min/Max/Sum
+     */
+
+    // ordering of the following operations *really* matters!
+    if (distinct != null) {
+      result = new DistinctExitOperation(distinct).apply(result);
+    }
+
+    for(Order order : orders) {
+      result = new OrderExitOperation(order, sessionFactoryImplementor).apply(result);
+    }
+    if (firstResult != null) {
+      result = new FirstResultExitOperation(firstResult).apply(result);
+    }
+    if (maxResults != null) {
+      result = new MaxResultsExitOperation(maxResults).apply(result);
+    }
+
+    ProjectionExitOperationFactory factory = ProjectionExitOperationFactory
+        .getFactory();
+
+    if (rowCountProjection != null) {
+      result = factory.getProjectionExitOperation(rowCountProjection, sessionFactoryImplementor).apply(result);
+    }
+
+    // TODO(maulik) average should go here
+
+    // min, max, sum
+    if (aggregateProjection != null) {
+      result = factory.getProjectionExitOperation(aggregateProjection, sessionFactoryImplementor).apply(result);
+    }
+    return result;
+  }
+
+  /**
+   * Sets the session factory implementor
+   * @param sessionFactoryImplementor the session factory implementor to set
+   */
+  public void setSessionFactory(SessionFactoryImplementor sessionFactoryImplementor) {
+    this.sessionFactoryImplementor = sessionFactoryImplementor;
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the {@link CacheMode} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setCacheMode(CacheMode)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetCacheModeEvent implements CriteriaEvent {
+
+  // the CacheMode that we'll set on the Criteria when the event fires
+  private final CacheMode cacheMode;
+
+  /**
+   * Construct a CacheModeEvent
+   *
+   * @param cacheMode the {@link CacheMode} we'll set on the {@link Criteria}
+   * when the event fires.
+   */
+  public SetCacheModeEvent(CacheMode cacheMode) {
+    this.cacheMode = cacheMode;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setCacheMode(cacheMode);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheRegionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheRegionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheRegionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the cache region of a {@link Criteria} to be set lazily.
+ * @see Criteria#setCacheRegion(String)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetCacheRegionEvent implements CriteriaEvent {
+
+  // the cache region that we'll set on the Criteria when the event fires
+  private final String cacheRegion;
+
+  /**
+   * Construct a CacheRegionEvent
+   *
+   * @param cacheRegion the cache region we'll set on the {@link Criteria}
+   * when the event fires.
+   */
+  public SetCacheRegionEvent(String cacheRegion) {
+    this.cacheRegion = cacheRegion;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setCacheRegion(cacheRegion);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheableEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheableEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCacheableEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the cacheability of a {@link Criteria} to be set lazily.
+ * @see Criteria#setCacheable(boolean)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetCacheableEvent implements CriteriaEvent {
+
+  // the value to which we're going to set the cacheability of the Criteria
+  // when the event fires
+  private boolean cacheable;
+
+  /**
+   * Construct a SetCacheableEvent
+   *
+   * @param cacheable the value to which we'll set the cacheability when the event
+   * fires
+   */
+  public SetCacheableEvent(boolean cacheable) {
+    this.cacheable = cacheable;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setCacheable(cacheable);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCommentEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCommentEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetCommentEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the comment of a {@link Criteria} to be set lazily.
+ * @see Criteria#setComment(String)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetCommentEvent implements CriteriaEvent {
+
+  // the comment that we'll set on the Criteria when the event fires
+  private final String comment;
+
+  /**
+   * Construct a SetCommentEvent
+   *
+   * @param comment the comment we'll set on the {@link Criteria}
+   * when the event fires.
+   */
+  public SetCommentEvent(String comment) {
+    this.comment = comment;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setComment(comment);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.FetchMode;
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the {@link FetchMode} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setFetchMode(String, FetchMode)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetFetchModeEvent implements CriteriaEvent {
+
+  // the association path that will be set on the Criteria
+  private final String associationPath;
+
+  // the FetchMode that will be set on the Criteria
+  private final FetchMode mode;
+
+  /**
+   * Construct a SetFetchModeEvent
+   *
+   * @param associationPath the association path of the fetch mode
+   * we'll set on the {@link Criteria} when the event fires.
+   * @param mode the mode we'll set on the {@link Criteria} when the event fires.
+   */
+  public SetFetchModeEvent(String associationPath, FetchMode mode) {
+    this.associationPath = associationPath;
+    this.mode = mode;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setFetchMode(associationPath, mode);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchSizeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchSizeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFetchSizeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the fetch size of a {@link Criteria} to be set lazily.
+ * @see Criteria#setFetchSize(int)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetFetchSizeEvent implements CriteriaEvent {
+
+  // the fetchSize we'll set on the Criteria when the event fires.
+  private final int fetchSize;
+
+  /**
+   * Construct a SetFetchSizeEvent
+   *
+   * @param fetchSize the fetchSize that
+   * we'll set on the {@link Criteria} when the event fires.
+   */
+  public SetFetchSizeEvent(int fetchSize) {
+    this.fetchSize = fetchSize;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setFetchSize(fetchSize);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFirstResultEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFirstResultEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFirstResultEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the firstResult of a {@link Criteria} to be set lazily.
+ * @see Criteria#setFirstResult(int)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetFirstResultEvent implements CriteriaEvent {
+
+  // the firstResult that we'll set on the Criteria when the event fires
+  private final int firstResult;
+
+  /**
+   * Construct a SetFirstResultEvent
+   *
+   * @param firstResult the firstResult that
+   * we'll set on the {@link Criteria} when the event fires.
+   */
+  public SetFirstResultEvent(int firstResult) {
+    this.firstResult = firstResult;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setFirstResult(firstResult);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFlushModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFlushModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetFlushModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.FlushMode;
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the {@link FlushMode} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setFlushMode(FlushMode)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetFlushModeEvent implements CriteriaEvent {
+
+  // the flushMode we'll set on the Critiera when the event fires
+  private final FlushMode flushMode;
+
+  /**
+   * Construct a SetFlushModeEvent
+   *
+   * @param flushMode the flushMode that
+   * we'll set on the {@link Criteria} when the event fires.
+   */
+  public SetFlushModeEvent(FlushMode flushMode) {
+    this.flushMode = flushMode;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setFlushMode(flushMode);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetLockModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetLockModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetLockModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Criteria;
+import org.hibernate.LockMode;
+
+/**
+ * Event that allows the {@link LockMode} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setLockMode(LockMode)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetLockModeEvent implements CriteriaEvent {
+
+  private enum MethodSig {
+    LOCK_MODE,
+    LOCK_MODE_AND_ALIAS
+  }
+
+  // tells us which overload of setLockMode to use
+  private final MethodSig methodSig;
+
+  // the LockMode we'll set on the Criteria when the event fires
+  private final LockMode lockMode;
+
+  // the alias for which we'll set the lock mode on the Criteria when the event
+  // fires.  Can be null
+  private final String alias;
+
+  /**
+   * Construct a SetLockModeEvent
+   *
+   * @param methodSig tells us which overload of setLockMode to use
+   * @param lockMode the lock mode we'll set when the event fires
+   * @param alias the alias for which we'll set the lcok mode when the event
+   * fires.  Can be null.
+   */
+  private SetLockModeEvent(
+      MethodSig methodSig,
+      LockMode lockMode,
+      /*@Nullable*/ String alias) {
+    this.methodSig = methodSig;
+    this.lockMode = lockMode;
+    this.alias = alias;
+  }
+
+  /**
+   * Construct a SetLockModeEvent
+   *
+   * @param lockMode the lock mode we'll set when the event fires
+   */
+  public SetLockModeEvent(LockMode lockMode) {
+    this(MethodSig.LOCK_MODE, lockMode, null);
+  }
+
+  /**
+   * Construct a SetLockModeEvent
+   *
+   * @param lockMode the lock mode we'll set when the event fires
+   * @param alias the alias for which we'll set the lock mode
+   * when the event fires
+   */
+  public SetLockModeEvent(LockMode lockMode, String alias) {
+    this(MethodSig.LOCK_MODE_AND_ALIAS, lockMode, alias);
+  }
+
+  public void onEvent(Criteria crit) {
+    switch (methodSig) {
+      case LOCK_MODE:
+        crit.setLockMode(lockMode);
+        break;
+      case LOCK_MODE_AND_ALIAS:
+        crit.setLockMode(alias, lockMode);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown constructor type for SetLockModeEvent: " + methodSig);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetMaxResultsEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetMaxResultsEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetMaxResultsEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the maxResults of a {@link Criteria} to be set lazily.
+ * @see Criteria#setMaxResults(int)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetMaxResultsEvent implements CriteriaEvent {
+
+  // the maxResults we'll set when the event fires
+  private final int maxResults;
+
+  /**
+   * Constructs a SetMaxResultsEvent
+   *
+   * @param maxResults the maxResults we'll set on the {@link Criteria} when
+   * the event fires.
+   */
+  public SetMaxResultsEvent(int maxResults) {
+    this.maxResults = maxResults;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setMaxResults(maxResults);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetProjectionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetProjectionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetProjectionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Projection;
+
+/**
+ * Event that allows the {@link Projection} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setProjection(Projection)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetProjectionEvent implements CriteriaEvent {
+
+  // the Projection we'll set on the Critiera when the event fires
+  private final Projection projection;
+
+  /**
+   * Constructs a SetProjectionEvent
+   *
+   * @param projection the projection we'll set on the {@link Criteria} when the
+   * event fires.
+   */
+  public SetProjectionEvent(Projection projection) {
+    this.projection = projection;
+  }
+
+
+  public void onEvent(Criteria crit) {
+    crit.setProjection(projection);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetResultTransformerEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetResultTransformerEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetResultTransformerEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the {@link ResultTransformer} of a {@link Criteria} to be set lazily.
+ * @see Criteria#setResultTransformer(ResultTransformer)
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetResultTransformerEvent implements CriteriaEvent {
+
+  // the resultTransformer we'll set on the Critieria when the event fires
+  private final ResultTransformer resultTransformer;
+
+  /**
+   * Constructs a SetResultTransformerEvent
+   *
+   * @param resultTransformer the resultTransformer we'll set on the {@link Criteria} when
+   * the event fires.
+   */
+  public SetResultTransformerEvent(ResultTransformer resultTransformer) {
+    this.resultTransformer = resultTransformer;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setResultTransformer(resultTransformer);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetTimeoutEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetTimeoutEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SetTimeoutEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Event that allows the timeout of a {@link Criteria} to be set lazily.
+ * @see Criteria#setTimeout(int)   
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetTimeoutEvent implements CriteriaEvent {
+
+  // the timeout we'll set on the Criteria when the event fires.
+  private final int timeout;
+
+  /**
+   * Constructs a SetTimeoutEvent
+   *
+   * @param timeout the timeout we'll set on the {@link Criteria} when the
+   * event fires.
+   */
+  public SetTimeoutEvent(int timeout) {
+    this.timeout = timeout;
+  }
+
+  public void onEvent(Criteria crit) {
+    crit.setTimeout(timeout);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteria.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteria.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteria.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Interface for a shard-aware {@link Criteria} implementation.
+ * @see Criteria
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardedCriteria extends Criteria {
+
+  /**
+   * @return the CriteriaId of this ShardedCriteria instance.
+   */
+  CriteriaId getCriteriaId();
+
+  /**
+   *
+   * @return the CriteriaFactory of this ShardedCriteria instance.
+   */
+  CriteriaFactory getCriteriaFactory();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,440 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.exit.ConcatenateListsExitStrategy;
+import org.hibernate.shards.strategy.exit.FirstNonNullResultExitStrategy;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projection;
+import org.hibernate.transform.ResultTransformer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Concrete implementation of the {@link ShardedCriteria} interface.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedCriteriaImpl implements ShardedCriteria {
+  
+  // unique id for this ShardedCriteria
+  private final CriteriaId criteriaId;
+
+  // the shards we know about
+  private final List<Shard> shards;
+
+  // a factory that knows how to create actual Criteria objects
+  private final CriteriaFactory criteriaFactory;
+
+  // the shard access strategy we use when we execute the Criteria
+  // across multiple shards
+  private final ShardAccessStrategy shardAccessStrategy;
+
+  // the criteria collector we use to process the results of executing
+  // the Criteria across multiple shards
+  private final ExitOperationsCriteriaCollector criteriaCollector;
+
+  /**
+   * Construct a ShardedCriteriaImpl
+   *
+   * @param criteriaId unique id for this ShardedCriteria
+   * @param shards the shards that this ShardedCriteria is aware of
+   * @param criteriaFactory factory that knows how to create concrete {@link Criteria} objects
+   * @param shardAccessStrategy the access strategy we use when we execute this
+   * ShardedCriteria across multiple shards.
+   */
+  public ShardedCriteriaImpl(
+      CriteriaId criteriaId,
+      List<Shard> shards,
+      CriteriaFactory criteriaFactory,
+      ShardAccessStrategy shardAccessStrategy) {
+    this.criteriaId = criteriaId;
+    this.shards = shards;
+    this.criteriaFactory = criteriaFactory;
+    this.shardAccessStrategy = shardAccessStrategy;
+    this.criteriaCollector = new ExitOperationsCriteriaCollector();
+    criteriaCollector.setSessionFactory(shards.get(0).getSessionFactoryImplementor());
+  }
+
+  public CriteriaId getCriteriaId() {
+    return criteriaId;
+  }
+
+  public CriteriaFactory getCriteriaFactory() {
+    return criteriaFactory;
+  }
+
+  /**
+   * @return any Criteria, or null if we don't have one
+   */
+  private /*@Nullable*/ Criteria getSomeCriteria() {
+    for (Shard shard : shards) {
+      Criteria crit = shard.getCriteriaById(criteriaId);
+      if (crit != null) {
+        return crit;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * @return any Criteria.  If no Criteria has been established we establish
+   * one and return it.
+   */
+  private Criteria getOrEstablishSomeCriteria() {
+    Criteria crit = getSomeCriteria();
+    if(crit == null) {
+      Shard shard = shards.get(0);
+      crit = shard.establishCriteria(this);
+    }
+    return crit;
+  }
+
+  public String getAlias() {
+    return getOrEstablishSomeCriteria().getAlias();
+  }
+
+  public Criteria setProjection(Projection projection) {
+    criteriaCollector.addProjection(projection);
+    return this;
+  }
+
+  public Criteria add(Criterion criterion) {
+    CriteriaEvent event = new AddCriterionEvent(criterion);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).add(criterion);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria addOrder(Order order) {
+    criteriaCollector.addOrder(order);
+    return this;
+  }
+
+  public Criteria setFetchMode(String associationPath, FetchMode mode)
+      throws HibernateException {
+    CriteriaEvent event = new SetFetchModeEvent(associationPath, mode);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setFetchMode(associationPath, mode);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setLockMode(LockMode lockMode) {
+    CriteriaEvent event = new SetLockModeEvent(lockMode);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setLockMode(lockMode);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setLockMode(String alias, LockMode lockMode) {
+    CriteriaEvent event = new SetLockModeEvent(lockMode, alias);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setLockMode(lockMode);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria createAlias(String associationPath, String alias)
+      throws HibernateException {
+    CriteriaEvent event = new CreateAliasEvent(associationPath, alias);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).createAlias(associationPath, alias);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria createAlias(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    CriteriaEvent event = new CreateAliasEvent(associationPath, alias, joinType);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId)
+            .createAlias(associationPath, alias, joinType);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  private static final Iterable<CriteriaEvent> NO_CRITERIA_EVENTS =
+      Collections.unmodifiableList(new ArrayList<CriteriaEvent>());
+
+  /**
+   * Creating sharded subcriteria is tricky.  We need to give the client a
+   * reference to a ShardedSubcriteriaImpl (which to the client just looks like
+   * a Criteria object).  Then, for each shard where the Criteria has already been
+   * established we need to create the actual subcriteria, and for each shard
+   * where the Criteria has not yet been established we need to register an
+   * event that will create the Subcriteria when the Criteria is established.
+   */
+  private ShardedSubcriteriaImpl createSubcriteria(SubcriteriaFactory factory) {
+
+    ShardedSubcriteriaImpl subcrit = new ShardedSubcriteriaImpl(shards, this);
+
+    for (Shard shard : shards) {
+      Criteria crit = shard.getCriteriaById(criteriaId);
+      if(crit != null) {
+        factory.createSubcriteria(crit, NO_CRITERIA_EVENTS);
+      } else {
+        CreateSubcriteriaEvent event =
+            new CreateSubcriteriaEvent(factory, subcrit.getSubcriteriaRegistrar(shard));
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return subcrit;
+  }
+
+  public Criteria createCriteria(String associationPath)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, int joinType)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, joinType);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, String alias)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, alias);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, alias, joinType);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria setResultTransformer(ResultTransformer resultTransformer) {
+    CriteriaEvent event = new SetResultTransformerEvent(resultTransformer);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId)
+            .setResultTransformer(resultTransformer);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setMaxResults(int maxResults) {
+    criteriaCollector.setMaxResults(maxResults);
+
+    return this;
+  }
+
+  public Criteria setFirstResult(int firstResult) {
+    criteriaCollector.setFirstResult(firstResult);
+    return this;
+  }
+
+  public Criteria setFetchSize(int fetchSize) {
+    CriteriaEvent event = new SetFetchSizeEvent(fetchSize);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setFetchSize(fetchSize);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setTimeout(int timeout) {
+    CriteriaEvent event = new SetTimeoutEvent(timeout);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setTimeout(timeout);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheable(boolean cacheable) {
+    CriteriaEvent event = new SetCacheableEvent(cacheable);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setCacheable(cacheable);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheRegion(String cacheRegion) {
+    CriteriaEvent event = new SetCacheRegionEvent(cacheRegion);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setCacheRegion(cacheRegion);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setComment(String comment) {
+    CriteriaEvent event = new SetCommentEvent(comment);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setComment(comment);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setFlushMode(FlushMode flushMode) {
+    CriteriaEvent event = new SetFlushModeEvent(flushMode);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setFlushMode(flushMode);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheMode(CacheMode cacheMode) {
+    CriteriaEvent event = new SetCacheModeEvent(cacheMode);
+    for (Shard shard : shards) {
+      if (shard.getCriteriaById(criteriaId) != null) {
+        shard.getCriteriaById(criteriaId).setCacheMode(cacheMode);
+      } else {
+        shard.addCriteriaEvent(criteriaId, event);
+      }
+    }
+    return this;
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public ScrollableResults scroll(ScrollMode scrollMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list() throws HibernateException {
+
+    // build a shard operation and apply it across all shards
+    ShardOperation<List<Object>> shardOp = new ShardOperation<List<Object>>() {
+      public List<Object> execute(Shard shard) {
+        shard.establishCriteria(ShardedCriteriaImpl.this);
+        return shard.list(criteriaId);
+      }
+
+      public String getOperationName() {
+        return "list()";
+      }
+    };
+    /**
+     * We don't support shard selection for criteria queries.  If you want
+     * custom shards, create a ShardedSession with only the shards you want.
+     * We're going to concatenate all our results and then use our
+     * criteria collector to do post processing.
+     */
+    return
+        shardAccessStrategy.apply(
+            shards,
+            shardOp,
+            new ConcatenateListsExitStrategy(),
+            criteriaCollector);
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    // build a shard operation and apply it across all shards
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        shard.establishCriteria(ShardedCriteriaImpl.this);
+        return shard.uniqueResult(criteriaId);
+      }
+
+      public String getOperationName() {
+        return "uniqueResult()";
+      }
+    };
+    /**
+     * We don't support shard selection for criteria queries.  If you want
+     * custom shards, create a ShardedSession with only the shards you want.
+     * We're going to return the first non-null result we get from a shard.
+     */
+    return
+        shardAccessStrategy.apply(
+            shards,
+            shardOp,
+            new FirstNonNullResultExitStrategy<Object>(),
+            criteriaCollector);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteria.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteria.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteria.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.impl.CriteriaImpl;
+
+/**
+ * Interface describing a {@link CriteriaImpl.Subcriteria}
+ * that is shard-aware.  A ShardedSubcriteria must know how to provide
+ * a reference to its parent {@link ShardedCriteria}.
+ * @see CriteriaImpl.Subcriteria
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+interface ShardedSubcriteria extends Criteria {
+
+  /**
+   * @return the owning ShardedCriteria
+   */
+  ShardedCriteria getParentCriteria();
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteriaImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteriaImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/ShardedSubcriteriaImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,437 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Preconditions;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.impl.CriteriaImpl;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projection;
+import org.hibernate.transform.ResultTransformer;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Concrete implementation of the {@link ShardedSubcriteria} interface.
+ * You'll notice that this class does not extend {@link ShardedCriteria}.
+ * Why? Because {@link CriteriaImpl.Subcriteria} doesn't extend {@link Criteria}.  We
+ * don't actually need the entire {@link Criteria} interface.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+class ShardedSubcriteriaImpl implements ShardedSubcriteria {
+
+  // all shards that we're aware of
+  final List<Shard> shards;
+
+  // our parent. As with CriteriaImpl, we pass-through certain operations
+  // to our parent
+  final ShardedCriteria parent;
+
+  // maps shards to actual Criteria objects
+  private final Map<Shard, Criteria> shardToCriteriaMap = Maps.newHashMap();
+
+  // maps shards to lists of criteria events that need to be applied
+  // when the actual Criteria objects are established
+  private final Map<Shard, List<CriteriaEvent>> shardToEventListMap = Maps.newHashMap();
+
+  /**
+   * Construct a ShardedSubcriteriaImpl
+   *
+   * @param shards the shards that we're aware of
+   * @param parent our parent
+   */
+  public ShardedSubcriteriaImpl(List<Shard> shards, ShardedCriteria parent) {
+    Preconditions.checkNotNull(shards);
+    Preconditions.checkNotNull(parent);
+    Preconditions.checkArgument(!shards.isEmpty());
+    this.shards = shards;
+    this.parent = parent;
+    // let's set up our maps
+    for(Shard shard : shards) {
+      shardToCriteriaMap.put(shard, null);
+      shardToEventListMap.put(shard, Lists.<CriteriaEvent>newArrayList());
+    }
+  }
+
+  /**
+   * @return Returns an actual Criteria object, or null if none have been allocated.
+   */
+  private /*@Nullable*/ Criteria getSomeSubcriteria() {
+    for (Criteria crit : shardToCriteriaMap.values()) {
+      if (crit != null) {
+        return crit;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * @return Returns an actual Criteria object.  If no actual Criteria object
+   * has been allocated, allocate one and return it.
+   */
+  private Criteria getOrEstablishSomeSubcriteria() {
+    Criteria crit = getSomeSubcriteria();
+    if(crit == null) {
+      Shard shard = shards.get(0);
+      // this should trigger the creation of all subcriteria for the parent
+      shard.establishCriteria(parent);
+    }
+    return getSomeSubcriteria();
+  }
+
+  public String getAlias() {
+    return getOrEstablishSomeSubcriteria().getAlias();
+  }
+
+  public Criteria setProjection(Projection projection) {
+    CriteriaEvent event = new SetProjectionEvent(projection);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setProjection(projection);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria add(Criterion criterion) {
+    CriteriaEvent event = new AddCriterionEvent(criterion);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).add(criterion);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria addOrder(Order order) {
+    CriteriaEvent event = new AddOrderEvent(order);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).addOrder(order);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setFetchMode(String associationPath, FetchMode mode)
+      throws HibernateException {
+    CriteriaEvent event = new SetFetchModeEvent(associationPath, mode);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setFetchMode(associationPath, mode);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setLockMode(LockMode lockMode) {
+    CriteriaEvent event = new SetLockModeEvent(lockMode);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setLockMode(lockMode);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setLockMode(String alias, LockMode lockMode) {
+    CriteriaEvent event = new SetLockModeEvent(lockMode, alias);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setLockMode(alias, lockMode);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria createAlias(String associationPath, String alias)
+      throws HibernateException {
+    CriteriaEvent event = new CreateAliasEvent(associationPath, alias);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).createAlias(associationPath, alias);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria createAlias(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    CriteriaEvent event = new CreateAliasEvent(associationPath, alias, joinType);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).createAlias(associationPath, alias, joinType);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setResultTransformer(ResultTransformer resultTransformer) {
+    CriteriaEvent event = new SetResultTransformerEvent(resultTransformer);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setResultTransformer(resultTransformer);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  /**
+   * TODO(maxr)
+   * This clearly isn't what people want.  We should be building an
+   * exit strategy that returns once we've accumulated maxResults
+   * across _all_ shards, not each shard.
+   */
+  public Criteria setMaxResults(int maxResults) {
+    CriteriaEvent event = new SetMaxResultsEvent(maxResults);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setMaxResults(maxResults);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setFirstResult(int firstResult) {
+    CriteriaEvent event = new SetFirstResultEvent(firstResult);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setFirstResult(firstResult);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setFetchSize(int fetchSize) {
+    CriteriaEvent event = new SetFetchSizeEvent(fetchSize);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setFetchSize(fetchSize);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setTimeout(int timeout) {
+    CriteriaEvent event = new SetTimeoutEvent(timeout);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setTimeout(timeout);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheable(boolean cacheable) {
+    CriteriaEvent event = new SetCacheableEvent(cacheable);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setCacheable(cacheable);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheRegion(String cacheRegion) {
+    CriteriaEvent event = new SetCacheRegionEvent(cacheRegion);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setCacheRegion(cacheRegion);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setComment(String comment) {
+    CriteriaEvent event = new SetCommentEvent(comment);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setComment(comment);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setFlushMode(FlushMode flushMode) {
+    CriteriaEvent event = new SetFlushModeEvent(flushMode);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setFlushMode(flushMode);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public Criteria setCacheMode(CacheMode cacheMode) {
+    CriteriaEvent event = new SetCacheModeEvent(cacheMode);
+    for (Shard shard : shards) {
+      if (shardToCriteriaMap.get(shard) != null) {
+        shardToCriteriaMap.get(shard).setCacheMode(cacheMode);
+      } else {
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return this;
+  }
+
+  public List list() throws HibernateException {
+    // pass through to the parent
+    return getParentCriteria().list();
+  }
+
+  public ScrollableResults scroll() throws HibernateException {
+    // pass through to the parent
+    return getParentCriteria().scroll();
+  }
+
+  public ScrollableResults scroll(ScrollMode scrollMode)
+      throws HibernateException {
+    // pass through to the parent
+    return getParentCriteria().scroll(scrollMode);
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    // pass through to the parent
+    return getParentCriteria().uniqueResult();
+  }
+
+  private ShardedSubcriteriaImpl createSubcriteria(SubcriteriaFactory factory) {
+    // first build our sharded subcrit
+    ShardedSubcriteriaImpl subcrit = new ShardedSubcriteriaImpl(shards, parent);
+    for (Shard shard : shards) {
+      // see if we already have a concreate Criteria object for each shard
+      if (shardToCriteriaMap.get(shard) != null) {
+        // we already have a concreate Criteria for this shard, so create
+        // a subcrit for it using the provided factory
+        factory.createSubcriteria(this, shardToEventListMap.get(shard));
+      } else {
+        // we do not yet have a concrete Criteria object for this shard
+        // so register an event that will create a proper subcrit when we do
+        CreateSubcriteriaEvent event = new CreateSubcriteriaEvent(factory, subcrit.getSubcriteriaRegistrar(shard));
+        shardToEventListMap.get(shard).add(event);
+      }
+    }
+    return subcrit;
+  }
+
+  SubcriteriaRegistrar getSubcriteriaRegistrar(final Shard shard) {
+    return new SubcriteriaRegistrar() {
+
+      public void establishSubcriteria(Criteria parentCriteria, SubcriteriaFactory subcriteriaFactory) {
+        List<CriteriaEvent> criteriaEvents = shardToEventListMap.get(shard);
+        // create the subcrit with the proper list of events
+        Criteria newCrit = subcriteriaFactory.createSubcriteria(parentCriteria, criteriaEvents);
+        // clear the list of events
+        criteriaEvents.clear();
+        // add it to our map
+        shardToCriteriaMap.put(shard, newCrit);
+      }
+    };
+  }
+
+  public Criteria createCriteria(String associationPath)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, int joinType)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, joinType);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, String alias)
+      throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, alias);
+    return createSubcriteria(factory);
+  }
+
+  public Criteria createCriteria(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    SubcriteriaFactory factory = new SubcriteriaFactoryImpl(associationPath, alias, joinType);
+    return createSubcriteria(factory);
+  }
+
+  public ShardedCriteria getParentCriteria() {
+    return parent;
+  }
+
+  Map<Shard, Criteria> getShardToCriteriaMap() {
+    return shardToCriteriaMap;
+  }
+
+  Map<Shard, List<CriteriaEvent>> getShardToEventListMap() {
+    return shardToEventListMap;
+  }
+
+  interface SubcriteriaRegistrar {
+
+    void establishSubcriteria(Criteria parentCriteria, SubcriteriaFactory subcriteriaFactory);
+
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * Interface describing an object tha knows how to create {@link Criteria}.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public interface SubcriteriaFactory {
+
+  /**
+   * Create a sub {@link Criteria} with the given parent and events
+   *
+   * @param parent the parent
+   * @param events the events to apply
+   * @return a criteria with the given parent and events
+   */
+  Criteria createSubcriteria(Criteria parent, Iterable<CriteriaEvent> events);
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/criteria/SubcriteriaFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,140 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.shards.session.ShardedSessionException;
+
+/**
+ * Concrete implementation of the {@link SubcriteriaFactory} interface.
+ * Used to lazily create {@link org.hibernate.impl.CriteriaImpl.Subcriteria}
+ * @see Criteria#createCriteria(String)
+ * @see Criteria#createCriteria(String, int)
+ * @see Criteria#createCriteria(String, String)
+ * @see Criteria#createCriteria(String, String, int)
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class SubcriteriaFactoryImpl implements SubcriteriaFactory {
+
+  private enum MethodSig {
+    ASSOCIATION,
+    ASSOCIATION_AND_JOIN_TYPE,
+    ASSOCIATION_AND_ALIAS,
+    ASSOCIATION_AND_ALIAS_AND_JOIN_TYPE
+  }
+
+  // used to tell us which overload of createCriteria to invoke
+  private final MethodSig methodSig;
+
+  // the association we'll pass to createCriteria
+  private final String association;
+
+  // the join type we'll pass to createCriteria.  Can be null.
+  private final int joinType;
+
+  // the alias we'll pass to createCriteria.  Can be null.
+  private final String alias;
+
+  /**
+   * Construct a SubcriteriaFactoryImpl
+   *
+   * @param methodSig used to tell us which overload of createCriteria to invoke
+   * @param association the association we'll pass to createCriteria
+   * @param joinType the join type we'll pass to createCriteria.  Can be null.
+   * @param alias the alias we'll pass to createCriteria.  Can be null.
+   */
+  private SubcriteriaFactoryImpl(
+      MethodSig methodSig,
+      String association,
+      /*@Nullable*/ int joinType,
+      /*@Nullable*/ String alias) {
+    this.methodSig = methodSig;
+    this.association = association;
+    this.joinType = joinType;
+    this.alias = alias;
+  }
+
+  /**
+   * Construct a SubcriteriaFactoryImpl
+   *
+   * @param association the association we'll pass to createCriteria
+   */
+  public SubcriteriaFactoryImpl(String association) {
+    this(MethodSig.ASSOCIATION, association, 0, null);
+  }
+
+  /**
+   * Construct a SubcriteriaFactoryImpl
+   *
+   * @param association the association we'll pass to createCriteria
+   * @param joinType the join type we'll pass to createCriteria
+   */
+  public SubcriteriaFactoryImpl(String association, int joinType) {
+    this(MethodSig.ASSOCIATION_AND_JOIN_TYPE, association, joinType, null);
+  }
+
+  /**
+   * Construct a SubcriteriaFactoryImpl
+   *
+   * @param association the association we'll pass to createCriteria
+   * @param alias the alias we'll pass to createCriteria
+   */
+  public SubcriteriaFactoryImpl(String association, String alias) {
+    this(MethodSig.ASSOCIATION_AND_ALIAS, association, 0, alias);
+  }
+
+  /**
+   * Construct a SubcriteriaFactoryImpl
+   *
+   * @param association the association we'll pass to createCriteria
+   * @param alias the alias we'll pass to createCriteria
+   * @param joinType the join type we'll pass to createCriteria
+   */
+  public SubcriteriaFactoryImpl(String association, String alias, int joinType) {
+    this(MethodSig.ASSOCIATION_AND_ALIAS_AND_JOIN_TYPE, association, joinType, alias);
+  }
+
+  public Criteria createSubcriteria(Criteria parent, Iterable<CriteriaEvent> events) {
+    // call the right overload to actually create the Criteria
+    Criteria crit;
+    switch (methodSig) {
+      case ASSOCIATION:
+        crit = parent.createCriteria(association);
+        break;
+      case ASSOCIATION_AND_JOIN_TYPE:
+        crit = parent.createCriteria(association, joinType);
+        break;
+      case ASSOCIATION_AND_ALIAS:
+        crit = parent.createCriteria(association, alias);
+        break;
+      case ASSOCIATION_AND_ALIAS_AND_JOIN_TYPE:
+        crit = parent.createCriteria(association, alias, joinType);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown constructor type for subcriteria creation: " + methodSig);
+    }
+    // apply the events
+    for(CriteriaEvent event : events) {
+      event.onEvent(crit);
+    }
+    return crit;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionFactoryImplementor.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionFactoryImplementor.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionFactoryImplementor.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.engine;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.session.ShardedSessionFactory;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Internal interface for implementors of ShardedSessionFactory
+ *
+ * @author Tomislav Nad (tomislav at google.com)
+ */
+public interface ShardedSessionFactoryImplementor extends ShardedSessionFactory, SessionFactoryImplementor {
+
+  Map<SessionFactoryImplementor, Set<ShardId>> getSessionFactoryShardIdMap();
+
+  boolean containsFactory(SessionFactoryImplementor factory);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionImplementor.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionImplementor.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/engine/ShardedSessionImplementor.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.engine;
+
+import org.hibernate.shards.session.ShardedSession;
+import org.hibernate.shards.Shard;
+
+import java.util.List;
+
+/**
+ * Defines the internal contract between the <tt>ShardedSession</tt> and other
+ * parts of Hibernate Shards.
+ *
+ * @see ShardedSession the interface to the application
+ * @see org.hibernate.shards.session.ShardedSessionImpl the actual implementation
+ *
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public interface ShardedSessionImplementor {
+
+  /**
+   * Gets all the shards the ShardedSession is spanning.
+   *
+   * @return list of all shards the ShardedSession is associated with
+   */
+  List<Shard> getShards();
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/GeneratorRequiringControlSessionProvider.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/GeneratorRequiringControlSessionProvider.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/GeneratorRequiringControlSessionProvider.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.session.ControlSessionProvider;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public interface GeneratorRequiringControlSessionProvider {
+
+  void setControlSessionProvider(ControlSessionProvider provider);
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardEncodingIdentifierGenerator.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardEncodingIdentifierGenerator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardEncodingIdentifierGenerator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.ShardId;
+
+import org.hibernate.id.IdentifierGenerator;
+
+import java.io.Serializable;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public interface ShardEncodingIdentifierGenerator extends IdentifierGenerator {
+
+  ShardId extractShardId(Serializable identifier);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedTableHiLoGenerator.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedTableHiLoGenerator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedTableHiLoGenerator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.session.ControlSessionProvider;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.id.TableHiLoGenerator;
+
+import java.io.Serializable;
+
+/**
+ * TableHiLoGenerator which uses control shard to store table with hi values.
+ *
+ * @see org.hibernate.id.TableHiLoGenerator
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+
+public class ShardedTableHiLoGenerator extends TableHiLoGenerator implements GeneratorRequiringControlSessionProvider {
+
+  private ControlSessionProvider controlSessionProvider;
+
+  @Override
+  public Serializable generate(SessionImplementor session, Object obj)
+      throws HibernateException {
+    Serializable id;
+    SessionImplementor controlSession = null;
+    try {
+      controlSession = controlSessionProvider.openControlSession();
+      id = superGenerate(controlSession, obj);
+    } finally {
+      if (controlSession != null) {
+        ((Session)controlSession).close();
+      }
+    }
+    return id;
+  }
+
+  public void setControlSessionProvider(ControlSessionProvider provider) {
+    this.controlSessionProvider = provider;
+  }
+
+  Serializable superGenerate(SessionImplementor controlSession, Object obj) {
+    return super.generate(controlSession, obj);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedUUIDGenerator.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedUUIDGenerator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/id/ShardedUUIDGenerator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Preconditions;
+import org.hibernate.shards.session.ShardedSessionImpl;
+
+import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.id.UUIDHexGenerator;
+import org.hibernate.type.Type;
+import org.hibernate.util.PropertiesHelper;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.util.Properties;
+
+/**
+ * Supports generation of either 32-character hex String UUID or 128 bit
+ * BigInteger UUID that encodes the shard.
+ *
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedUUIDGenerator extends UUIDHexGenerator implements ShardEncodingIdentifierGenerator {
+
+  private IdType idType;
+  private int shardId;
+
+  private static String ZERO_STRING = "00000000000000000000000000000000";
+  private static String ID_TYPE_PROPERTY = "sharded-uuid-type";
+
+  private static enum IdType { STRING, INTEGER }
+
+  private int getShardId() {
+    ShardId shardId = ShardedSessionImpl.getCurrentSubgraphShardId();
+    Preconditions.checkState(shardId != null);
+    return shardId.getId();
+  }
+
+  public ShardId extractShardId(Serializable identifier) {
+    Preconditions.checkNotNull(identifier);
+    String hexId;
+    switch(idType) {
+      case STRING:
+        hexId = (String)identifier;
+        return new ShardId(Integer.decode("0x" + hexId.substring(0, 4)));
+      case INTEGER:
+        String strippedHexId = ((BigInteger)identifier).toString(16);
+        hexId = ZERO_STRING.substring(0, 32 - strippedHexId.length()) + strippedHexId;
+        return new ShardId(Integer.decode("0x" + hexId.substring(0, hexId.length()-28)));
+      default:
+        // should never get here
+        throw new IllegalStateException("ShardedUUIDGenerator was not configured properly");
+    }
+  }
+
+  @Override
+  public Serializable generate(SessionImplementor session, Object object) {
+    String id =  new StringBuilder(32).append(format((short)getShardId()))
+                                      .append(format(getIP()))
+                                      .append(format((short)(getJVM()>>>16)))
+                                      .append(format(getHiTime()))
+                                      .append(format(getLoTime()))
+                                      .append(format(getCount()))
+                                      .toString();
+    switch(idType) {
+      case STRING:
+        return id;
+      case INTEGER:
+        return new BigInteger(id, 16);
+      default:
+        // should never get here
+        throw new IllegalStateException("ShardedUUIDGenerator was not configured properly");
+    }
+  }
+
+  @Override
+  public void configure(Type type, Properties params, Dialect d) {
+    this.idType = IdType.valueOf(PropertiesHelper.getString(ID_TYPE_PROPERTY, params, "INTEGER"));
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/BaseShardLoadBalancer.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/BaseShardLoadBalancer.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/BaseShardLoadBalancer.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.BaseHasShardIdList;
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * Helpful base class for ShardLoadBalancer implementations.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseShardLoadBalancer extends BaseHasShardIdList implements ShardLoadBalancer {
+
+  /**
+   * Construct a BaseShardLoadBalancer
+   * @param shardIds the ShardIds that we're going to balance across
+   */
+  protected BaseShardLoadBalancer(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+
+  public ShardId getNextShardId() {
+    return shardIds.get(getNextIndex());
+  }
+
+  /**
+   * @return the index of the next ShardId we should return
+   */
+  protected abstract int getNextIndex();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RandomShardLoadBalancer.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RandomShardLoadBalancer.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RandomShardLoadBalancer.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Random selection load balancing algorithm.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class RandomShardLoadBalancer extends BaseShardLoadBalancer {
+
+  private final Random rand = new Random(System.currentTimeMillis());
+
+  /**
+   * Construct a RandomShardLoadBalancer
+   * @param shardIds the ShardIds that we're balancing across
+   */
+  public RandomShardLoadBalancer(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+
+  @Override
+  protected int getNextIndex() {
+    // Implementation of nextInt() seems to indicate that this method is
+    // threadsafe.  I sure hope I'm right about that.
+    return rand.nextInt();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancer.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancer.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancer.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Round robin load balancing algorithm.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class RoundRobinShardLoadBalancer extends BaseShardLoadBalancer {
+
+  // Can be shared by multiple threads so access to the counter
+  // needs to be threadsafe.
+  private final AtomicInteger nextIndex = new AtomicInteger();
+
+  /**
+   * Construct a RoundRobinShardLoadBalancer
+   * @param shardIds the ShardIds that we're balancing across
+   */
+  public RoundRobinShardLoadBalancer(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+
+  @Override
+  protected int getNextIndex() {
+    return nextIndex.getAndIncrement() % getShardIds().size();
+  }
+}
+

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/ShardLoadBalancer.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/ShardLoadBalancer.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/loadbalance/ShardLoadBalancer.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.ShardId;
+
+/**
+ * Describes a load balance for shards.
+ * Implementations are expected to be threadsafe.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardLoadBalancer {
+
+  /**
+   * @return the next ShardId
+   */
+  ShardId getNextShardId();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/package-info.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/package-info.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/package-info.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+/**
+ * Hibernate Shards.
+ *
+ * This package and its subpackages adds support for sharding (more
+ * commonly known as horizontal partitioning) to Hibernate.
+ *
+ * Conventions for this project:
+ *
+ * Unless otherwise noted, all actual parameter values and are expected to be
+ * non-null.
+ *
+ * Unless otherwise noted, all return values will be non-null.
+ *
+ * Unless otherwise noted, Collections passed as actual parameter values can be
+ * empty.
+ *
+ * Unless otherwise noted, returned Collections can be empty.
+ *
+ * Unless otherwise noted, Maps passed as actual parameter values are expected
+ * to contain non-null keys and non-null values.
+ *
+ * Unless otherwise noted, returned Maps will not contain null keys or null
+ * values.
+ *
+ * Unless otherwise noted, concrete classes are NOT threadsafe.
+ */

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/AdHocQueryFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/AdHocQueryFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/AdHocQueryFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class AdHocQueryFactoryImpl implements QueryFactory {
+
+  private final String queryString;
+
+  public AdHocQueryFactoryImpl(String queryString) {
+    this.queryString = queryString;
+  }
+
+  public Query createQuery(Session session) {
+    return session.createQuery(queryString);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ExitOperationsQueryCollector.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ExitOperationsQueryCollector.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ExitOperationsQueryCollector.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.util.List;
+
+/**
+ * Exit operations for queries is essentially not implemented. Its intended use
+ * is to record a set of aggregation type operations to be executed on the
+ * combined results for a query executed on each shard.
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ExitOperationsQueryCollector implements ExitOperationsCollector {
+
+  public List<Object> apply(List<Object> result) {
+    return result;
+  }
+
+  public void setSessionFactory(SessionFactoryImplementor sessionFactoryImplementor) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/NamedQueryFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/NamedQueryFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/NamedQueryFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Facilitates use of named queries when using ShardedQuery.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class NamedQueryFactoryImpl implements QueryFactory {
+
+  private final String queryName;
+
+  public NamedQueryFactoryImpl(String queryName) {
+    this.queryName = queryName;
+  }
+
+  public Query createQuery(Session session) {
+    return session.getNamedQuery(queryName);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+
+/**
+ * Interface for events that can be lazily applied to a
+ * {@link org.hibernate.Query}. Useful because we don't allocate a
+ * {@link org.hibernate.Query} until we actually need it, and programmers
+ * might be calling a variety of methods against
+ * {@link org.hibernate.shards.query.ShardedQueryImpl}
+ * which need to be applied to the actual {@link org.hibernate.Query} when
+ * it is allocated.
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+
+public interface QueryEvent {
+
+  /**
+   * Apply the event
+   * @param query the Query to apply the event to
+   */
+  void onEvent(Query query);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public interface QueryFactory {
+
+  Query createQuery(Session session);
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryId.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryId.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryId.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class QueryId {
+
+  private final int id;
+
+  public QueryId(int id) {
+    this.id = id;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof QueryId)) {
+      return false;
+    }
+
+    final QueryId queryId = (QueryId) o;
+
+    if (id != queryId.id) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    return id;
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryResult.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryResult.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/QueryResult.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class QueryResult {
+
+  private final Map<Shard, List> resultMap = Maps.newHashMap();
+
+  private final List<?> entityList = Lists.newArrayList();
+
+  public Map<Shard, List> getResultMap() {
+    return Collections.unmodifiableMap(resultMap);
+  }
+
+  public void add(Shard shard, List list) {
+    resultMap.put(shard, list);
+    entityList.addAll(list);
+  }
+
+  public void add(QueryResult result) {
+    resultMap.putAll(result.getResultMap());
+    entityList.addAll(result.getEntityList());
+  }
+
+  public List getEntityList() {
+    return entityList;
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigDecimalEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigDecimalEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigDecimalEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.math.BigDecimal;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBigDecimalEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final BigDecimal val;
+  private final String name;
+
+  private SetBigDecimalEvent(CtorType ctorType, int position, BigDecimal val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetBigDecimalEvent(int position, BigDecimal val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetBigDecimalEvent(String name, BigDecimal val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setBigDecimal(position, val);
+        break;
+      case NAME_VAL:
+        query.setBigDecimal(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetBigDecmialEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigIntegerEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigIntegerEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBigIntegerEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.math.BigInteger;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBigIntegerEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final BigInteger val;
+  private final String name;
+
+  private SetBigIntegerEvent(CtorType ctorType, int position, BigInteger val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetBigIntegerEvent(int position, BigInteger val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetBigIntegerEvent(String name, BigInteger val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setBigInteger(position, val);
+        break;
+      case NAME_VAL:
+        query.setBigInteger(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetEvent: " + ctorType);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBinaryEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBinaryEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBinaryEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBinaryEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final byte[] val;
+  private final String name;
+
+  private SetBinaryEvent(CtorType ctorType, int position, byte[] val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetBinaryEvent(int position, byte[] val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetBinaryEvent(String name, byte[] val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setBinary(position, val);
+        break;
+      case NAME_VAL:
+        query.setBinary(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetBinaryEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBooleanEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBooleanEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetBooleanEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBooleanEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final boolean val;
+  private final String name;
+
+  private SetBooleanEvent(CtorType ctorType, int position, boolean val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetBooleanEvent(int position, boolean val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetBooleanEvent(String name, boolean val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setBoolean(position, val);
+        break;
+      case NAME_VAL:
+        query.setBoolean(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetBooleanEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetByteEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetByteEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetByteEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetByteEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final byte val;
+  private final String name;
+
+  private SetByteEvent(CtorType ctorType, int position, byte val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetByteEvent(int position, byte val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetByteEvent(String name, byte val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setByte(position, val);
+        break;
+      case NAME_VAL:
+        query.setByte(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetByteEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.CacheMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCacheModeEvent implements QueryEvent {
+
+  private final CacheMode cacheMode;
+
+  public SetCacheModeEvent(CacheMode cacheMode) {
+    this.cacheMode = cacheMode;
+  }
+
+  public void onEvent(Query query) {
+    query.setCacheMode(cacheMode);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheRegionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheRegionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheRegionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCacheRegionEvent implements QueryEvent {
+
+  private final String cacheRegion;
+
+  public SetCacheRegionEvent(String cacheRegion) {
+    this.cacheRegion = cacheRegion;
+  }
+
+  public void onEvent(Query query) {
+    query.setCacheRegion(cacheRegion);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheableEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheableEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCacheableEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCacheableEvent implements QueryEvent {
+
+  private final boolean cacheable;
+
+  public SetCacheableEvent(boolean cacheable) {
+    this.cacheable = cacheable;
+  }
+
+  public void onEvent(Query query) {
+    query.setCacheable(cacheable);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarDateEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarDateEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarDateEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Calendar;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCalendarDateEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Calendar val;
+  private final String name;
+
+  private SetCalendarDateEvent(CtorType ctorType, int position, Calendar val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetCalendarDateEvent(int position, Calendar val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetCalendarDateEvent(String name, Calendar val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setCalendarDate(position, val);
+        break;
+      case NAME_VAL:
+        query.setCalendarDate(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetCalendarDateEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCalendarEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Calendar;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCalendarEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Calendar val;
+  private final String name;
+
+  private SetCalendarEvent(CtorType ctorType, int position, Calendar val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetCalendarEvent(int position, Calendar val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetCalendarEvent(String name, Calendar val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setCalendar(position, val);
+        break;
+      case NAME_VAL:
+        query.setCalendar(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetCalendarEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCharacterEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCharacterEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCharacterEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCharacterEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private CtorType ctorType;
+  private final int position;
+  private final char val;
+  private final String name;
+
+  private SetCharacterEvent(CtorType ctorType, int position, char val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetCharacterEvent(int position, char val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetCharacterEvent(String name, char val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setCharacter(position, val);
+        break;
+      case NAME_VAL:
+        query.setCharacter(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetCharacterEvent: " + ctorType);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCommentEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCommentEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetCommentEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCommentEvent implements QueryEvent {
+
+  private final String comment;
+
+  public SetCommentEvent(String comment) {
+    this.comment = comment;
+  }
+
+  public void onEvent(Query query) {
+    query.setComment(comment);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDateEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDateEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDateEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetDateEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Date val;
+  private final String name;
+
+  private SetDateEvent(CtorType ctorType, int position, Date val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetDateEvent(int position, Date val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetDateEvent(String name, Date val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setDate(position, val);
+        break;
+      case NAME_VAL:
+        query.setDate(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetDateEvent: " + ctorType);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDoubleEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDoubleEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetDoubleEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetDoubleEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final double val;
+  private final String name;
+
+  private SetDoubleEvent(CtorType ctorType, int position, double val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetDoubleEvent(int position, double val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetDoubleEvent(String name, double val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setDouble(position, val);
+        break;
+      case NAME_VAL:
+        query.setDouble(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetDoubleEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetEntityEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetEntityEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetEntityEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetEntityEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Object val;
+  private final String name;
+
+  private SetEntityEvent(CtorType ctorType, int position, Object val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetEntityEvent(int position, Object val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetEntityEvent(String name, Object val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setEntity(position, val);
+        break;
+      case NAME_VAL:
+        query.setEntity(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetEntityEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFetchSizeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFetchSizeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFetchSizeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetFetchSizeEvent implements QueryEvent {
+
+  private final int fetchSize;
+
+  public SetFetchSizeEvent(int fetchSize) {
+    this.fetchSize = fetchSize;
+  }
+
+  public void onEvent(Query query) {
+    query.setFetchSize(fetchSize);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFirstResultEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFirstResultEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFirstResultEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetFirstResultEvent implements QueryEvent {
+
+  private final int firstResult;
+
+  public SetFirstResultEvent(int firstResult) {
+    this.firstResult = firstResult;
+  }
+
+  public void onEvent(Query query) {
+    query.setFirstResult(firstResult);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFloatEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFloatEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFloatEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetFloatEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final float val;
+  private final String name;
+
+  private SetFloatEvent(CtorType ctorType, int position, float val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetFloatEvent(int position, float val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetFloatEvent(String name, float val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setFloat(position, val);
+        break;
+      case NAME_VAL:
+        query.setFloat(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetFloatEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFlushModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFlushModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetFlushModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.FlushMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetFlushModeEvent implements QueryEvent {
+
+  private final FlushMode flushMode;
+
+  public SetFlushModeEvent(FlushMode flushMode) {
+    this.flushMode = flushMode;
+  }
+
+  public void onEvent(Query query) {
+    query.setFlushMode(flushMode);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetIntegerEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetIntegerEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetIntegerEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetIntegerEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final int val;
+  private final String name;
+
+  private SetIntegerEvent(CtorType ctorType, int position, int val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetIntegerEvent(int position, int val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetIntegerEvent(String name, int val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setInteger(position, val);
+        break;
+      case NAME_VAL:
+        query.setInteger(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetIntegerEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLocaleEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLocaleEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLocaleEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Locale;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetLocaleEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Locale val;
+  private final String name;
+
+  private SetLocaleEvent(CtorType ctorType, int position, Locale val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetLocaleEvent(int position, Locale val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetLocaleEvent(String name, Locale val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setLocale(position, val);
+        break;
+      case NAME_VAL:
+        query.setLocale(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetLocaleEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLockModeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLockModeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLockModeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.LockMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetLockModeEvent implements QueryEvent {
+
+  private final String alias;
+  private final LockMode lockMode;
+
+  public SetLockModeEvent(String alias, LockMode lockMode) {
+    this.alias = alias;
+    this.lockMode = lockMode;
+  }
+
+  public void onEvent(Query query) {
+    query.setLockMode(alias, lockMode);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLongEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLongEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetLongEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetLongEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final long val;
+  private final String name;
+
+  private SetLongEvent(CtorType ctorType, int position, Long val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetLongEvent(int position, long val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetLongEvent(String name, long val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setLong(position, val);
+        break;
+      case NAME_VAL:
+        query.setLong(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetLongEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetMaxResultsEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetMaxResultsEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetMaxResultsEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+
+public class SetMaxResultsEvent implements QueryEvent {
+  private final int maxResults;
+
+  public SetMaxResultsEvent(int maxResults) {
+    this.maxResults = maxResults;
+  }
+
+  public void onEvent(Query query) {
+    query.setMaxResults(maxResults);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,89 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParameterEvent implements QueryEvent {
+  private static enum CtorType {
+    POSITION_VAL,
+    POSITION_VAL_TYPE,
+    NAME_VAL,
+    NAME_VAL_TYPE,
+  }
+
+  private final CtorType ctorType;
+
+  private final int position;
+  private final Object val;
+  private final Type type;
+  private final String name;
+
+
+  private SetParameterEvent(CtorType ctorType, int position, String name, Object val, Type type) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.type = type;
+    this.name = name;
+  }
+
+  public SetParameterEvent(int position, Object val, Type type) {
+    this(CtorType.POSITION_VAL_TYPE, position, null, val, type);
+  }
+
+  public SetParameterEvent(String name, Object val, Type type) {
+    this(CtorType.NAME_VAL_TYPE, -1, name, val, type);
+  }
+
+  public SetParameterEvent(int position, Object val) {
+    this(CtorType.POSITION_VAL, position, null, val, null);
+  }
+
+  public SetParameterEvent(String name, Object val) {
+    this(CtorType.NAME_VAL, -1, name, val, null);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setParameter(position, val);
+        break;
+      case POSITION_VAL_TYPE:
+        query.setParameter(position, val, type);
+        break;
+      case NAME_VAL:
+        query.setParameter(name, val);
+        break;
+      case NAME_VAL_TYPE:
+        query.setParameter(name, val, type);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetParameterEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterListEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterListEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParameterListEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,91 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+import java.util.Collection;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParameterListEvent implements QueryEvent {
+
+  private static enum CtorType {
+    NAME_VALS_COLL_TYPE,
+    NAME_VALS_COLL,
+    NAME_VALS_OBJ_ARR,
+    NAME_VALS_OBJ_ARR_TYPE
+  }
+
+  private final CtorType ctorType;
+  private final String name;
+  private final Collection valsColl;
+  private final Object[] valsArr;
+  private final Type type;
+
+  private SetParameterListEvent(CtorType ctorType, String name, Collection valsColl, Object[] valsArr, Type type) {
+    this.ctorType = ctorType;
+    this.name = name;
+    this.valsColl = valsColl;
+    this.valsArr = valsArr;
+    this.type = type;
+  }
+
+  public SetParameterListEvent(String name, Collection vals, Type type) {
+    this(CtorType.NAME_VALS_COLL_TYPE, name, vals, null, type);
+  }
+
+  public SetParameterListEvent(String name, Collection vals) {
+    this(CtorType.NAME_VALS_COLL, name, vals, null, null);
+  }
+
+  public SetParameterListEvent(String name, Object[] vals) {
+    this(CtorType.NAME_VALS_OBJ_ARR, name, null, vals, null);
+  }
+
+  public SetParameterListEvent(String name, Object[] vals, Type type) {
+    this(CtorType.NAME_VALS_OBJ_ARR_TYPE, name, null, vals, type);
+  }
+
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case NAME_VALS_COLL_TYPE:
+        query.setParameterList(name, valsColl, type);
+        break;
+      case NAME_VALS_COLL:
+        query.setParameterList(name, valsColl);
+        break;
+      case NAME_VALS_OBJ_ARR:
+        query.setParameterList(name, valsArr);
+        break;
+      case NAME_VALS_OBJ_ARR_TYPE:
+        query.setParameterList(name, valsArr, type);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetParameterListEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParametersEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParametersEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetParametersEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParametersEvent implements QueryEvent {
+
+  private final Object[] values;
+  private final Type[] types;
+
+  public SetParametersEvent(Object[] values, Type[] types) {
+    this.values = values;
+    this.types = types;
+  }
+
+  public void onEvent(Query query) {
+    query.setParameters(values, types);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetPropertiesEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetPropertiesEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetPropertiesEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Map;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetPropertiesEvent implements QueryEvent {
+
+  private enum MethodSig {
+    OBJECT, MAP
+  }
+
+  private final MethodSig sig;
+  private final Object bean;
+  private final Map map;
+
+  public SetPropertiesEvent(Object bean) {
+    this(MethodSig.OBJECT, bean, null);
+  }
+
+  public SetPropertiesEvent(Map map) {
+    this(MethodSig.MAP, null, map);
+  }
+
+  private SetPropertiesEvent(MethodSig sig, Object bean, Map map) {
+    this.sig = sig;
+    this.bean = bean;
+    this.map = map;
+  }
+
+  public void onEvent(Query query) {
+    switch (sig) {
+      case OBJECT:
+        query.setProperties(bean);
+        break;
+      case MAP:
+        query.setProperties(map);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown sig in SetPropertiesEvent: " + sig);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetReadOnlyEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetReadOnlyEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetReadOnlyEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetReadOnlyEvent implements QueryEvent {
+
+  private final boolean readOnly;
+
+  public SetReadOnlyEvent(boolean readOnly) {
+    this.readOnly = readOnly;
+  }
+
+  public void onEvent(Query query) {
+    query.setReadOnly(readOnly);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetResultTransformerEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetResultTransformerEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetResultTransformerEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.transform.ResultTransformer;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetResultTransformerEvent implements QueryEvent {
+
+  private final ResultTransformer transformer;
+
+  public SetResultTransformerEvent(ResultTransformer transformer) {
+    this.transformer = transformer;
+  }
+
+  public void onEvent(Query query) {
+    query.setResultTransformer(transformer);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetSerializableEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetSerializableEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetSerializableEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.io.Serializable;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetSerializableEvent implements QueryEvent {
+
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Serializable val;
+  private final String name;
+
+  private SetSerializableEvent(CtorType ctorType, int position, Serializable val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetSerializableEvent(int position, Serializable val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetSerializableEvent(String name, Serializable val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setSerializable(position, val);
+        break;
+      case NAME_VAL:
+        query.setSerializable(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetSerializableEvent: " + ctorType);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetShortEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetShortEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetShortEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetShortEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Short val;
+  private final String name;
+
+  private SetShortEvent(CtorType ctorType, int position, Short val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetShortEvent(int position, Short val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetShortEvent(String name, Short val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setShort(position, val);
+        break;
+      case NAME_VAL:
+        query.setShort(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetShortEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetStringEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetStringEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetStringEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetStringEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final String val;
+  private final String name;
+
+  private SetStringEvent(CtorType ctorType, int position, String val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetStringEvent(int position, String val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetStringEvent(String name, String val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setString(position, val);
+        break;
+      case NAME_VAL:
+        query.setString(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetStringEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTextEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTextEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTextEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTextEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final String val;
+  private final String name;
+
+  private SetTextEvent(CtorType ctorType, int position, String val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetTextEvent(int position, String val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetTextEvent(String name, String val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setText(position, val);
+        break;
+      case NAME_VAL:
+        query.setText(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetTextEvent: " + ctorType);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTimeEvent implements QueryEvent {
+
+  private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Date val;
+  private final String name;
+
+  private SetTimeEvent(CtorType ctorType, int position, Date val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetTimeEvent(int position, Date val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetTimeEvent(String name, Date val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setTime(position, val);
+        break;
+      case NAME_VAL:
+        query.setTime(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetTimeEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeoutEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeoutEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimeoutEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTimeoutEvent implements QueryEvent {
+
+  private final int timeout;
+
+  public SetTimeoutEvent(int timeout) {
+    this.timeout = timeout;
+  }
+
+  public void onEvent(Query query) {
+    query.setTimeout(timeout);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimestampEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimestampEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/SetTimestampEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.session.ShardedSessionException;
+
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTimestampEvent implements QueryEvent {
+
+   private static enum CtorType {
+    POSITION_VAL,
+    NAME_VAL
+  }
+
+  private final CtorType ctorType;
+  private final int position;
+  private final Date val;
+  private final String name;
+
+  private SetTimestampEvent(CtorType ctorType, int position, Date val, String name) {
+    this.ctorType = ctorType;
+    this.position = position;
+    this.val = val;
+    this.name = name;
+  }
+
+  public SetTimestampEvent(int position, Date val) {
+    this(CtorType.POSITION_VAL, position, val, null);
+  }
+
+  public SetTimestampEvent(String name, Date val) {
+    this(CtorType.NAME_VAL, -1, val, name);
+  }
+
+  public void onEvent(Query query) {
+    switch(ctorType) {
+      case POSITION_VAL:
+        query.setTimestamp(position, val);
+        break;
+      case NAME_VAL:
+        query.setTimestamp(name, val);
+        break;
+      default:
+        throw new ShardedSessionException(
+            "Unknown ctor type in SetTimestampEvent: " + ctorType);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQuery.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQuery.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQuery.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+
+/**
+ * ShardedQuery extends the Query interface to provide the ability to query
+ * across shards.
+ *
+ * @see org.hibernate.Query
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+
+public interface ShardedQuery extends Query {
+
+  QueryId getQueryId();
+
+  QueryFactory getQueryFactory();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQueryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQueryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/query/ShardedQueryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,1043 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.exit.ConcatenateListsExitStrategy;
+import org.hibernate.shards.strategy.exit.FirstNonNullResultExitStrategy;
+import org.hibernate.shards.util.Preconditions;
+
+import org.hibernate.CacheMode;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.Query;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Concrete implementation of ShardedQuery provided by Hibernate Shards. This
+ * implementation introduces limits to the HQL language; mostly around
+ * limits and aggregation. Its approach is simply to execute the query on
+ * each shard and compile the results in a list, or if a unique result is
+ * desired, the fist non-null result is returned.
+ *
+ * The setFoo methods are implemented using a set of classes that implement
+ * the QueryEvent interface and are called SetFooEvent. These query events
+ * are used to call setFoo with the appropriate arguments on each Query that
+ * is executed on a shard.
+ *
+ * @see org.hibernate.shards.query.QueryEvent
+ *
+ * {@inheritDoc}
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ShardedQueryImpl implements ShardedQuery {
+  private final QueryId queryId;
+  private final List<Shard> shards;
+  private final QueryFactory queryFactory;
+  private final ShardAccessStrategy shardAccessStrategy;
+
+  /**
+   * The queryCollector is not used in ShardedQueryImpl as it would require
+   * this implementation to parse the query string and extract which exit
+   * operations would be appropriate. This member is a place holder for
+   * future development.
+   */
+  private final ExitOperationsQueryCollector queryCollector;
+
+  /**
+   * Constructor for ShardedQueryImpl
+   *
+   * @param queryId the id of the query
+   * @param shards list of shards on which this query will be executed
+   * @param queryFactory factory that knows how to create the actual query we'll execute
+   * @param shardAccessStrategy the shard strategy for this query
+   */
+  public ShardedQueryImpl(QueryId queryId,
+                          List<Shard> shards,
+                          QueryFactory queryFactory,
+                          ShardAccessStrategy shardAccessStrategy) {
+    this.queryId = queryId;
+    this.shards = shards;
+    this.queryFactory = queryFactory;
+    this.shardAccessStrategy = shardAccessStrategy;
+    this.queryCollector = new ExitOperationsQueryCollector();
+
+    Preconditions.checkState(!shards.isEmpty());
+    for (Shard shard : shards) {
+      Preconditions.checkNotNull(shard);
+    }
+  }
+
+  public QueryId getQueryId() {
+    return queryId;
+  }
+
+  public QueryFactory getQueryFactory() {
+    return queryFactory;
+  }
+
+  private Query getSomeQuery() {
+    for (Shard shard : shards) {
+      Query query = shard.getQueryById(queryId);
+      if (query != null) {
+        return query;
+      }
+    }
+    return null;
+  }
+
+  private Query getOrEstablishSomeQuery() {
+    Query query = getSomeQuery();
+    if (query == null) {
+      Shard shard = shards.get(0);
+      query = shard.establishQuery(this);
+    }
+    return query;
+  }
+
+  public String getQueryString() {
+    return getOrEstablishSomeQuery().getQueryString();
+  }
+
+  public Type[] getReturnTypes() throws HibernateException {
+    return getOrEstablishSomeQuery().getReturnTypes();
+  }
+
+  public String[] getReturnAliases() throws HibernateException {
+    return getOrEstablishSomeQuery().getReturnAliases();
+  }
+
+  public String[] getNamedParameters() throws HibernateException {
+    return getOrEstablishSomeQuery().getNamedParameters();
+  }
+
+  /**
+   * This method currently wraps list().
+   *
+   * {@inheritDoc}
+   *
+   * @return an iterator over the results of the query
+   * @throws HibernateException
+   */
+  public Iterator iterate() throws HibernateException {
+    /**
+     * TODO(maulik) Hibernate in Action says these two methods are equivalent
+     * in what the content that they return but are implemented differently.
+     * We should figure out the difference and implement correctly.
+     */
+    return list().iterator();
+  }
+
+  /**
+   * Scrolling is unsupported. Current implementation throws an
+   * UnsupportedOperationException. A dumb implementation of scroll might be
+   * possible; however it would provide no performance benefit. An intelligent
+   * implementation would require re-querying shards frequently and a
+   * deterministic way to complie results.
+   */
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Scrolling is unsupported. Current implementation throws an
+   * UnsupportedOperationException. A dumb implementation of scroll might be
+   * possible; however it would provide no performance benefit. An intelligent
+   * implementation would require re-querying shards frequently and a
+   * deterministic way to complie results.
+   */
+  public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * The implementation executes the query on each shard and concatenates the
+   * results.
+   *
+   * {@inheritDoc}
+   *
+   * @return a list containing the concatenated results of executing the
+   * query on all shards
+   * @throws HibernateException
+   */
+  public List list() throws HibernateException {
+    ShardOperation<List<Object>> shardOp = new ShardOperation<List<Object>>() {
+      public List<Object> execute(Shard shard) {
+        shard.establishQuery(ShardedQueryImpl.this);
+        return shard.list(queryId);
+      }
+
+      public String getOperationName() {
+        return "list()";
+      }
+    };
+    /**
+     * We don't support shard selection for HQL queries.  If you want
+     * custom shards, create a ShardedSession with only the shards you want.
+     */
+    return
+      shardAccessStrategy.apply(
+              shards,
+              shardOp,
+              new ConcatenateListsExitStrategy(),
+              queryCollector);
+
+  }
+
+  /**
+   * The implementation executes the query on each shard and returns the first
+   * non-null result.
+   *
+   * {@inheritDoc}
+   *
+   * @return the first non-null result, or null if no non-null result found
+   * @throws HibernateException
+   */
+  public Object uniqueResult() throws HibernateException {
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        shard.establishQuery(ShardedQueryImpl.this);
+        return shard.uniqueResult(queryId);
+      }
+
+      public String getOperationName() {
+        return "uniqueResult()";
+      }
+    };
+   /**
+    * We don't support shard selection for HQL queries.  If you want
+    * custom shards, create a ShardedSession with only the shards you want.
+    */
+    return
+      shardAccessStrategy.apply(
+              shards,
+              shardOp,
+              new FirstNonNullResultExitStrategy<Object>(),
+              queryCollector);
+  }
+
+  /**
+   * ExecuteUpdate is not supported and throws an
+   * UnsupportedOperationException.
+   *
+   * @throws HibernateException
+   */
+  public int executeUpdate() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setMaxResults(int maxResults) {
+    SetMaxResultsEvent event = new SetMaxResultsEvent(maxResults);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setMaxResults(maxResults);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+
+    return this;
+  }
+
+  public Query setFirstResult(int firstResult) {
+    QueryEvent event = new SetFirstResultEvent(firstResult);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setFirstResult(firstResult);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setReadOnly(boolean readOnly) {
+    QueryEvent event = new SetReadOnlyEvent(readOnly);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setReadOnly(readOnly);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCacheable(boolean cacheable) {
+    QueryEvent event = new SetCacheableEvent(cacheable);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCacheable(cacheable);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCacheRegion(String cacheRegion) {
+    QueryEvent event = new SetCacheRegionEvent(cacheRegion);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCacheRegion(cacheRegion);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setTimeout(int timeout) {
+    QueryEvent event = new SetTimeoutEvent(timeout);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setTimeout(timeout);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setFetchSize(int fetchSize) {
+    QueryEvent event = new SetFetchSizeEvent(fetchSize);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setFetchSize(fetchSize);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setLockMode(String alias, LockMode lockMode) {
+    QueryEvent event = new SetLockModeEvent(alias, lockMode);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setLockMode(alias, lockMode);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setComment(String comment) {
+    QueryEvent event = new SetCommentEvent(comment);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setComment(comment);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setFlushMode(FlushMode flushMode) {
+    QueryEvent event = new SetFlushModeEvent(flushMode);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setFlushMode(flushMode);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCacheMode(CacheMode cacheMode) {
+    QueryEvent event = new SetCacheModeEvent(cacheMode);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCacheMode(cacheMode);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameter(int position, Object val, Type type) {
+    QueryEvent event = new SetParameterEvent(position, val, type);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameter(position, val, type);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameter(String name, Object val, Type type) {
+    QueryEvent event = new SetParameterEvent(name, val, type);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameter(name, val, type);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameter(int position, Object val) throws HibernateException {
+    QueryEvent event = new SetParameterEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameter(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameter(String name, Object val) throws HibernateException {
+    QueryEvent event = new SetParameterEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameter(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameters(Object[] values, Type[] types) throws HibernateException {
+    QueryEvent event = new SetParametersEvent(values, types);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameters(values, types);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
+    QueryEvent event = new SetParameterListEvent(name, vals, type);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameterList(name, vals, type);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameterList(String name, Collection vals) throws HibernateException {
+    QueryEvent event = new SetParameterListEvent(name, vals);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameterList(name, vals);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameterList(String name, Object[] vals, Type type) throws HibernateException {
+    QueryEvent event = new SetParameterListEvent(name, vals, type);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameterList(name, vals, type);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setParameterList(String name, Object[] vals) throws HibernateException {
+    QueryEvent event = new SetParameterListEvent(name, vals);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setParameterList(name, vals);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setProperties(Object bean) throws HibernateException {
+    QueryEvent event = new SetPropertiesEvent(bean);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setProperties(bean);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setString(int position, String val) {
+    QueryEvent event = new SetStringEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setString(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCharacter(int position, char val) {
+    QueryEvent event = new SetCharacterEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCharacter(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBoolean(int position, boolean val) {
+    QueryEvent event = new SetBooleanEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBoolean(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setByte(int position, byte val) {
+    QueryEvent event = new SetByteEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setByte(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setShort(int position, short val) {
+    QueryEvent event = new SetShortEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setShort(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setInteger(int position, int val) {
+    QueryEvent event = new SetIntegerEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setInteger(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setLong(int position, long val) {
+    QueryEvent event = new SetLongEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setLong(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setFloat(int position, float val) {
+    QueryEvent event = new SetFloatEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setFloat(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setDouble(int position, double val) {
+    QueryEvent event = new SetDoubleEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setDouble(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBinary(int position, byte[] val) {
+    QueryEvent event = new SetBinaryEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBinary(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setText(int position, String val) {
+    QueryEvent event = new SetTextEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setText(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setSerializable(int position, Serializable val) {
+    QueryEvent event = new SetSerializableEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setSerializable(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setLocale(int position, Locale locale) {
+    QueryEvent event = new SetLocaleEvent(position, locale);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setLocale(position, locale);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBigDecimal(int position, BigDecimal number) {
+    QueryEvent event = new SetBigDecimalEvent(position, number);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBigDecimal(position, number);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBigInteger(int position, BigInteger number) {
+    QueryEvent event = new SetBigIntegerEvent(position, number);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBigInteger(position, number);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setDate(int position, Date date) {
+    QueryEvent event = new SetDateEvent(position, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setDate(position, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setTime(int position, Date date) {
+    QueryEvent event = new SetTimeEvent(position, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setTime(position, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setTimestamp(int position, Date date) {
+    QueryEvent event = new SetTimestampEvent(position, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setTimestamp(position, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCalendar(int position, Calendar calendar) {
+    QueryEvent event = new SetCalendarEvent(position, calendar);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCalendar(position, calendar);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCalendarDate(int position, Calendar calendar) {
+    QueryEvent event = new SetCalendarDateEvent(position, calendar);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCalendarDate(position, calendar);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setString(String name, String val) {
+    QueryEvent event = new SetStringEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setString(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCharacter(String name, char val) {
+    QueryEvent event = new SetCharacterEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCharacter(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBoolean(String name, boolean val) {
+    QueryEvent event = new SetBooleanEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBoolean(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setByte(String name, byte val) {
+    QueryEvent event = new SetByteEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setByte(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setShort(String name, short val) {
+    QueryEvent event = new SetShortEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setShort(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setInteger(String name, int val) {
+    QueryEvent event = new SetIntegerEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setInteger(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setLong(String name, long val) {
+    QueryEvent event = new SetLongEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setLong(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setFloat(String name, float val) {
+    QueryEvent event = new SetFloatEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setFloat(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setDouble(String name, double val) {
+    QueryEvent event = new SetDoubleEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setDouble(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBinary(String name, byte[] val) {
+    QueryEvent event = new SetBinaryEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBinary(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setText(String name, String val) {
+    QueryEvent event = new SetTextEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setText(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setSerializable(String name, Serializable val) {
+    QueryEvent event = new SetSerializableEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setSerializable(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setLocale(String name, Locale locale) {
+    QueryEvent event = new SetLocaleEvent(name, locale);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setLocale(name, locale);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBigDecimal(String name, BigDecimal number) {
+    QueryEvent event = new SetBigDecimalEvent(name, number);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBigDecimal(name, number);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setBigInteger(String name, BigInteger number) {
+    QueryEvent event = new SetBigIntegerEvent(name, number);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setBigInteger(name, number);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setDate(String name, Date date) {
+    QueryEvent event = new SetDateEvent(name, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setDate(name, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setTime(String name, Date date) {
+    QueryEvent event = new SetTimeEvent(name, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setTime(name, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setTimestamp(String name, Date date) {
+    QueryEvent event = new SetTimestampEvent(name, date);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setTimestamp(name, date);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCalendar(String name, Calendar calendar) {
+    QueryEvent event = new SetCalendarEvent(name, calendar);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCalendar(name, calendar);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setCalendarDate(String name, Calendar calendar) {
+    QueryEvent event = new SetCalendarDateEvent(name, calendar);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setCalendarDate(name, calendar);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setEntity(int position, Object val) {
+    QueryEvent event = new SetEntityEvent(position, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setEntity(position, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setEntity(String name, Object val) {
+    QueryEvent event = new SetEntityEvent(name, val);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setEntity(name, val);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setResultTransformer(ResultTransformer transformer) {
+    QueryEvent event = new SetResultTransformerEvent(transformer);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setResultTransformer(transformer);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+
+  public Query setProperties(Map map) throws HibernateException {
+    QueryEvent event = new SetPropertiesEvent(map);
+    for (Shard shard : shards) {
+      if (shard.getQueryById(queryId) != null) {
+        shard.getQueryById(queryId).setProperties(map);
+      } else {
+        shard.addQueryEvent(queryId, event);
+      }
+    }
+    return this;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/BaseStatefulInterceptorFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/BaseStatefulInterceptorFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/BaseStatefulInterceptorFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.EmptyInterceptor;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseStatefulInterceptorFactory extends EmptyInterceptor implements StatefulInterceptorFactory {
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ControlSessionProvider.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ControlSessionProvider.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ControlSessionProvider.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.engine.SessionImplementor;
+
+/**
+ * Interface for any entity that can provide the control session.
+ * Control session is used to access control (meta)data which usually lives on
+ * only one shard.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public interface ControlSessionProvider {
+
+  /**
+   * Opens control session.
+   *
+   * @return control session
+   */
+  SessionImplementor openControlSession();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,171 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.CrossShardAssociationException;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Pair;
+import org.hibernate.shards.session.ShardedSessionImpl;
+import org.hibernate.shards.util.Iterables;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Preconditions;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.CallbackException;
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.ObjectNotFoundException;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Interceptor that looks at all associated objects and verifies that those
+ * objects are on the proper shard.  There is a definite performance impact
+ * associated with this interceptor since we'll end up resolving all the lazy
+ * associations.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+class CrossShardRelationshipDetectingInterceptor extends EmptyInterceptor {
+
+  private final ShardIdResolver shardIdResolver;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public CrossShardRelationshipDetectingInterceptor(ShardIdResolver shardIdResolver) {
+    Preconditions.checkNotNull(shardIdResolver);
+    this.shardIdResolver = shardIdResolver;
+  }
+
+  @Override
+  public boolean onFlushDirty(Object entity, Serializable id,
+      Object[] currentState, Object[] previousState, String[] propertyNames,
+      Type[] types) throws CallbackException {
+    ShardId expectedShardId = getAndRefreshExpectedShardId(entity);
+    Preconditions.checkNotNull(expectedShardId);
+
+    List<Collection<Object>> collections = null;
+    for(Pair<Type, Object> pair : buildListOfAssociations(types, currentState)) {
+      if(pair.getFirst().isCollectionType()) {
+        /**
+         * collection types are more expensive to evaluate (might involve
+         * lazy-loading the contents of the collection from the db), so
+         * let's hold off until the end on the chance that we can fail
+         * quickly.
+         */
+        if(collections == null) {
+          collections = Lists.newArrayList();
+        }
+        collections.add((Collection<Object>) pair.getSecond());
+      } else {
+        checkForConflictingShardId(entity.getClass().getName(), expectedShardId, pair.getSecond());
+      }
+    }
+    if(collections != null) {
+      checkIterable(entity.getClass().getName(), expectedShardId, Iterables.concat(collections));
+    }
+    return false;
+  }
+
+  static List<Pair<Type, Object>> buildListOfAssociations(Type[] types, Object[] currentState) {
+    // we assume types and current state are the same length
+    Preconditions.checkState(types.length == currentState.length);
+    List<Pair<Type, Object>> associationList = Lists.newArrayList();
+    for(int i = 0; i < types.length; i++) {
+      if(types[i] != null &&
+          currentState[i] != null &&
+          types[i].isAssociationType()) {
+        associationList.add(Pair.of(types[i], currentState[i]));
+      }
+    }
+    return associationList;
+}
+
+  void checkIterable(String classOfUpdatedObject, ShardId expectedShardId, Iterable<Object> iterable) {
+    for(Object obj : iterable) {
+      checkForConflictingShardId(classOfUpdatedObject, expectedShardId, obj);
+    }
+  }
+
+  void checkForConflictingShardId(String classOfUpdatedObject, ShardId expectedShardId, Object associatedObject) {
+    ShardId localShardId = null;
+    /*
+     * Here's something you wish you didn't need to know: If the associated
+     * object is an unitialized proxy and the object is not on the same
+     * shard as the shard with which the interceptor is associated, attempting
+     * to lookup the shard for the object will yield an ObjectNotFoundException
+     * that Hibernate will swallow, and getShardIdForObject will return null and
+     * the association will be let through.
+     * In order to avoid this, we check to see if the associated object is
+     * a proxy, and if it is we force it to initialize.
+     * If the associated object is a pojo or a proxy that has already been
+     * initialized, the call to getShardIdForObject will succeed.
+     */
+    if(associatedObject instanceof HibernateProxy) {
+      HibernateProxy hp = (HibernateProxy) associatedObject;
+      try {
+        hp.getHibernateLazyInitializer().initialize();
+      } catch(ObjectNotFoundException e) {
+        final String msg = String.format(
+            "Object of type %s is on shard %d but an associated object of type %s is on different shard.",
+            classOfUpdatedObject,
+            expectedShardId.getId(),
+            hp.getHibernateLazyInitializer().getPersistentClass().getName());
+        log.error(msg);
+        throw new CrossShardAssociationException(msg);
+      }
+    }
+    localShardId = shardIdResolver.getShardIdForObject(associatedObject);
+    if(localShardId != null) {
+      if(!localShardId.equals(expectedShardId)) {
+        final String msg = String.format(
+            "Object of type %s is on shard %d but an associated object of type %s is on shard %d.",
+            classOfUpdatedObject,
+            expectedShardId.getId(),
+            associatedObject.getClass().getName(),
+            localShardId.getId());
+        log.error(msg);
+        throw new CrossShardAssociationException(msg);
+      }
+    }
+  }
+
+  @Override
+  public void onCollectionUpdate(Object collection, Serializable key)
+      throws CallbackException {
+    ShardId expectedShardId = getAndRefreshExpectedShardId(((PersistentCollection)collection).getOwner());
+    Preconditions.checkNotNull(expectedShardId);
+    checkIterable("<Unknown>", expectedShardId, (Iterable<Object>) collection);
+  }
+
+  private ShardId getAndRefreshExpectedShardId(Object object) {
+    ShardId expectedShardId = shardIdResolver.getShardIdForObject(object);
+    if (expectedShardId == null) {
+      expectedShardId = ShardedSessionImpl.getCurrentSubgraphShardId();
+    } else {
+      ShardedSessionImpl.setCurrentSubgraphShardId(expectedShardId);
+    }
+    return expectedShardId;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecorator.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecorator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecorator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.util.InterceptorDecorator;
+
+import org.hibernate.CallbackException;
+import org.hibernate.Interceptor;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+
+/**
+ * Decorator that checks for cross shard relationships before delegating
+ * to the decorated interceptor.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+class CrossShardRelationshipDetectingInterceptorDecorator extends InterceptorDecorator {
+
+  private final CrossShardRelationshipDetectingInterceptor csrdi;
+
+  public CrossShardRelationshipDetectingInterceptorDecorator(
+      CrossShardRelationshipDetectingInterceptor csrdi,
+      Interceptor delegate) {
+    super(delegate);
+    this.csrdi = csrdi;
+  }
+
+  @Override
+  public boolean onFlushDirty(Object entity, Serializable id,
+      Object[] currentState, Object[] previousState, String[] propertyNames,
+      Type[] types) throws CallbackException {
+
+    // first give the cross relationship detector a chance
+    csrdi.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
+    // now pass it on
+    return
+        delegate.onFlushDirty(
+            entity,
+            id,
+            currentState,
+            previousState,
+            propertyNames,
+            types);
+  }
+
+  @Override
+  public void onCollectionUpdate(Object collection, Serializable key)
+      throws CallbackException {
+    // first give the cross relationship detector a chance
+    csrdi.onCollectionUpdate(collection, key);
+    // now pass it on
+    delegate.onCollectionUpdate(collection, key);
+  }
+
+  CrossShardRelationshipDetectingInterceptor getCrossShardRelationshipDetectingInterceptor() {
+    return csrdi;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/DisableFilterOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/DisableFilterOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/DisableFilterOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which disables specified filter.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class DisableFilterOpenSessionEvent implements OpenSessionEvent {
+
+  private final String filterName;
+
+  public DisableFilterOpenSessionEvent(String filterName) {
+    this.filterName = filterName;
+  }
+
+  public void onOpenSession(Session session) {
+    session.disableFilter(filterName);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/EnableFilterOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/EnableFilterOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/EnableFilterOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which enables specified filter.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class EnableFilterOpenSessionEvent implements OpenSessionEvent {
+
+  private final String filterName;
+
+  public EnableFilterOpenSessionEvent(String filterName) {
+    this.filterName = filterName;
+  }
+
+  public void onOpenSession(Session session) {
+    session.enableFilter(filterName);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/OpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/OpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/OpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * Interface for events that can be laziliy applied to a {@link org.hibernate.Session}.
+ * Useful because we don't allocate a {@link org.hibernate.Session} until we actually need it,
+ * and programmers might be calling a variety of methods against the
+ * {@link ShardedSession} which
+ * need to be applied to the actual {@link org.hibernate.Session}
+ * once the actual {@link org.hibernate.Session} is allocated.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface OpenSessionEvent {
+
+  /**
+   * Invokes any actions that have to occur when a session is opened.
+   *
+   * @param session Session which is being opened
+   */
+  void onOpenSession(Session session);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/RequiresSession.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/RequiresSession.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/RequiresSession.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * Interface describing an object that can have a Session set on it.  This
+ * is designed to be used in conjunction with stateful interceptors.
+ *
+ * @see StatefulInterceptorFactory
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface RequiresSession {
+  void setSession(Session session);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetCacheModeOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetCacheModeOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetCacheModeOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which sets the CacheMode.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetCacheModeOpenSessionEvent implements OpenSessionEvent {
+
+  private final CacheMode cacheMode;
+
+  public SetCacheModeOpenSessionEvent(CacheMode cacheMode) {
+    this.cacheMode = cacheMode;
+  }
+
+  public void onOpenSession(Session session) {
+    session.setCacheMode(cacheMode);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetFlushModeOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetFlushModeOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetFlushModeOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.FlushMode;
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which sets the FlushMode.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetFlushModeOpenSessionEvent implements OpenSessionEvent {
+
+  private final FlushMode flushMode;
+
+  public SetFlushModeOpenSessionEvent(FlushMode flushMode) {
+    this.flushMode = flushMode;
+  }
+
+  public void onOpenSession(Session session) {
+    session.setFlushMode(flushMode);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetReadOnlyOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetReadOnlyOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetReadOnlyOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which sets specified entity's readOnly flag.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+class SetReadOnlyOpenSessionEvent implements OpenSessionEvent {
+
+  private final Object entity;
+
+  private final boolean readOnly;
+
+  public SetReadOnlyOpenSessionEvent(Object entity, boolean readOnly) {
+    this.entity = entity;
+    this.readOnly = readOnly;
+  }
+
+  public void onOpenSession(Session session) {
+    session.setReadOnly(entity, readOnly);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetSessionOnRequiresSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetSessionOnRequiresSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetSessionOnRequiresSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which sets the provided Session on a RequiresSession.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetSessionOnRequiresSessionEvent implements OpenSessionEvent {
+
+  private final RequiresSession requiresSession;
+
+
+  public SetSessionOnRequiresSessionEvent(RequiresSession requiresSession) {
+    this.requiresSession = requiresSession;
+  }
+
+  public void onOpenSession(Session session) {
+    requiresSession.setSession(session);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetupTransactionOpenSessionEvent.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetupTransactionOpenSessionEvent.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SetupTransactionOpenSessionEvent.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardedTransaction;
+
+import org.hibernate.Session;
+
+/**
+ * OpenSessionEvent which adds newly opened session to the specified
+ * ShardedTransaction.
+ *
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class SetupTransactionOpenSessionEvent implements OpenSessionEvent {
+
+  private final ShardedTransaction shardedTransaction;
+
+  public SetupTransactionOpenSessionEvent(ShardedTransaction shardedTtransaction) {
+    this.shardedTransaction = shardedTtransaction;
+  }
+
+  public void onOpenSession(Session session) {
+    shardedTransaction.setupTransaction(session);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardIdResolver.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardIdResolver.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardIdResolver.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.Shard;
+
+import java.util.List;
+
+/**
+ * Interface for objects that are able to resolve shard of objects.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+interface ShardIdResolver {
+
+  /**
+   * Gets ShardId of the shard given object lives on. Only consideres given
+   * Shards.
+   *
+   * @param obj Object whose Shard should be resolved
+   * @param shardsToConsider Shards which should be considered during resolution
+   * @return ShardId of the shard the object lives on; null if shard could not be resolved
+   */
+  /*@Nullable*/ ShardId getShardIdForObject(Object obj, List<Shard> shardsToConsider);
+
+  /**
+   * Gets ShardId of the shard given object lives on.
+   *
+   * @param obj Object whose Shard should be resolved
+   * @return ShardId of the shard the object lives on; null if shard could not be resolved
+   */
+  /*@Nullable*/ ShardId getShardIdForObject(Object obj);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSession.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSession.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSession.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardId;
+
+import org.hibernate.classic.Session;
+
+
+/**
+ * The main runtime inteface between Java application and Hibernate Shards.<br>
+ * ShardedSession represents a logical transaction that might be spanning
+ * multiple shards. It follows the contract set by Session API, and adds some
+ * shard-related methods.
+ *
+ * @see ShardedSessionFactory
+ * @see Session
+ * @author maxr at google.com (Max Ross)
+ */
+public interface ShardedSession extends Session {
+
+  /**
+   * Gets the non-sharded session with which the objects is associated.
+   *
+   * @param obj  the object for which we want the Session
+   * @return the Session with which this object is associated, or null if the
+   * object is not associated with a session belonging to this ShardedSession
+   */
+  Session getSessionForObject(Object obj);
+
+  /**
+   * Gets the ShardId of the shard with which the objects is associated.
+   *
+   * @param obj  the object for which we want the Session
+   * @return the ShardId of the Shard with which this object is associated, or
+   * null if the object is not associated with a shard belonging to this
+   * ShardedSession
+   */
+  ShardId getShardIdForObject(Object obj);
+
+  /**
+   * Place the session into a state where every create operation takes place
+   * on the same shard.  Once the shard is locked on a session it cannot
+   * be unlocked.
+   */
+  void lockShard();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionException.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionException.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionException.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+/**
+ * Main exception used in Hibernate Shards.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionException extends RuntimeException {
+
+  public ShardedSessionException() {
+  }
+
+  public ShardedSessionException(String message) {
+    super(message);
+  }
+
+  public ShardedSessionException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public ShardedSessionException(Throwable cause) {
+    super(cause);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,78 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.session.ShardedSession;
+import org.hibernate.shards.ShardId;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.Interceptor;
+import org.hibernate.HibernateException;
+
+import java.util.List;
+
+/**
+ * Shard-aware extension to {@link SessionFactory}.  Similar to {@link SessionFactory},
+ * ShardedSessionFactory is threadsafe.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardedSessionFactory extends SessionFactory {
+
+  /**
+   * @return All an unmodifiable list of the {@link SessionFactory} objects contained within.
+   */
+  List<SessionFactory> getSessionFactories();
+
+  /**
+   * This method is provided to allow a client to work on a subset of
+   * shards or a specialized {@link ShardStrategyFactory}.  By providing
+   * the desired shardIds, the client can limit operations to these shards.
+   * Alternatively, this method can be used to create a ShardedSessionFactory
+   * with different strategies that might be appropriate for a specific operation.
+   *
+   * The factory returned will not be stored as one of the factories that would
+   * be returned by a call to getSessionFactories.
+   *
+   * @param shardIds
+   * @param shardStrategyFactory
+   * @return specially configured ShardedSessionFactory
+   */
+  ShardedSessionFactory getSessionFactory(List<ShardId> shardIds,
+      ShardStrategyFactory shardStrategyFactory);
+
+/**
+ * Create database connection(s) and open a <tt>ShardedSession</tt> on it,
+ * specifying an interceptor.
+ *
+ * @param interceptor a session-scoped interceptor
+ * @return ShardedSession
+ * @throws org.hibernate.HibernateException
+ */
+ ShardedSession openSession(Interceptor interceptor) throws HibernateException;
+
+  /**
+   * Create database connection(s) and open a <tt>ShardedSession</tt> on it.
+   *
+   * @return ShardedSession
+   * @throws org.hibernate.HibernateException
+   */
+  public ShardedSession openSession() throws HibernateException;
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,682 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Preconditions;
+import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
+import org.hibernate.shards.id.GeneratorRequiringControlSessionProvider;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.util.Iterables;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Sets;
+import org.hibernate.shards.util.Maps;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.MappingException;
+import org.hibernate.SessionFactory;
+import org.hibernate.StatelessSession;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.QueryCache;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cfg.Settings;
+import org.hibernate.classic.Session;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.engine.FilterDefinition;
+import org.hibernate.engine.NamedQueryDefinition;
+import org.hibernate.engine.NamedSQLQueryDefinition;
+import org.hibernate.engine.ResultSetMappingDefinition;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.query.QueryPlanCache;
+import org.hibernate.exception.SQLExceptionConverter;
+import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.metadata.CollectionMetadata;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.proxy.EntityNotFoundDelegate;
+import org.hibernate.stat.Statistics;
+import org.hibernate.stat.StatisticsImpl;
+import org.hibernate.stat.StatisticsImplementor;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.transaction.TransactionManager;
+
+/**
+ * Shard-aware implementation of {@link SessionFactory}.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionFactoryImpl implements ShardedSessionFactoryImplementor, ControlSessionProvider {
+
+  // the id of the control shard
+  private static final int CONTROL_SHARD_ID = 0;
+
+  // the SessionFactoryImplementor objects to which we delegate
+  private final List<SessionFactoryImplementor> sessionFactories;
+
+  // All classes that cannot be directly saved
+  private final Set<Class<?>> classesWithoutTopLevelSaveSupport;
+
+  // map of SessionFactories used by this ShardedSessionFactory (might be a subset of all SessionFactories)
+  private final Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap;
+
+  // map of all existing SessionFactories, used when creating a new ShardedSessionFactory for some subset of shards
+  private final Map<SessionFactoryImplementor, Set<ShardId>> fullSessionFactoryShardIdMap;
+
+  // The strategy we use for all shard-related operations
+  private final ShardStrategy shardStrategy;
+
+  // Reference to the SessionFactory we use for functionality that expects
+  // data to live in a single, well-known location (like distributed sequences)
+  private final SessionFactoryImplementor controlSessionFactory;
+
+  // flag to indicate whether we should do full cross-shard relationship
+  // checking (very slow)
+  private final boolean checkAllAssociatedObjectsForDifferentShards;
+
+  // Statistics aggregated across all contained SessionFactories
+  private final Statistics statistics = new StatisticsImpl(this);
+
+  // our lovely logger
+  private final Log log = LogFactory.getLog(getClass());
+
+  /**
+   * Constructs a ShardedSessionFactoryImpl
+   * @param shardIds The ids of the shards with which this SessionFactory
+   * should be associated.
+   * @param sessionFactoryShardIdMap Mapping of SessionFactories to shard ids.
+   * When using virtual shards, this map associates SessionFactories (physical
+   * shards) with virtual shards (shard ids).  Map cannot be empty.
+   * Map keys cannot be null.  Map values cannot be null or empty.
+   * @param shardStrategyFactory  factory that knows how to create the {@link ShardStrategy}
+   * that will be used for all shard-related operations
+   * @param classesWithoutTopLevelSaveSupport  All classes that cannot be saved
+   * as top-level objects
+   * @param checkAllAssociatedObjectsForDifferentShards  Flag that controls
+   * whether or not we do full cross-shard relationshp checking (very slow)
+   */
+  public ShardedSessionFactoryImpl(
+      List<ShardId> shardIds,
+      Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
+      ShardStrategyFactory shardStrategyFactory,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    Preconditions.checkNotNull(sessionFactoryShardIdMap);
+    Preconditions.checkArgument(!sessionFactoryShardIdMap.isEmpty());
+    Preconditions.checkNotNull(shardStrategyFactory);
+    Preconditions.checkNotNull(classesWithoutTopLevelSaveSupport);
+
+    this.sessionFactories = Lists.newArrayList(sessionFactoryShardIdMap.keySet());
+    this.sessionFactoryShardIdMap = Maps.newHashMap();
+    this.fullSessionFactoryShardIdMap = sessionFactoryShardIdMap;
+    this.classesWithoutTopLevelSaveSupport = Sets.newHashSet(classesWithoutTopLevelSaveSupport);
+    this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;
+    Set<ShardId> uniqueShardIds = Sets.newHashSet();
+    SessionFactoryImplementor controlSessionFactoryToSet = null;
+    for (Map.Entry<SessionFactoryImplementor, Set<ShardId>> entry : sessionFactoryShardIdMap.entrySet()) {
+      SessionFactoryImplementor implementor = entry.getKey();
+      Preconditions.checkNotNull(implementor);
+      Set<ShardId> shardIdSet = entry.getValue();
+      Preconditions.checkNotNull(shardIdSet);
+      Preconditions.checkArgument(!shardIdSet.isEmpty());
+      for (ShardId shardId : shardIdSet) {
+        // TODO(tomislav): we should change it so we specify control shard in configuration
+        if (shardId.getId() == CONTROL_SHARD_ID) {
+          controlSessionFactoryToSet = implementor;
+        }
+        if(!uniqueShardIds.add(shardId)) {
+          final String msg = String.format("Cannot have more than one shard with shard id %d.", shardId.getId());
+          log.error(msg);
+          throw new HibernateException(msg);
+        }
+        if (shardIds.contains(shardId)) {
+          if (!this.sessionFactoryShardIdMap.containsKey(implementor)) {
+            this.sessionFactoryShardIdMap.put(implementor, Sets.<ShardId>newHashSet());
+          }
+          this.sessionFactoryShardIdMap.get(implementor).add(shardId);
+        }
+      }
+    }
+    // make sure someone didn't associate a session factory with a shard id
+    // that isn't in the full list of shards
+    for (ShardId shardId : shardIds) {
+      Preconditions.checkState(uniqueShardIds.contains(shardId));
+    }
+    controlSessionFactory = controlSessionFactoryToSet;
+    // now that we have all our shard ids, construct our shard strategy
+    this.shardStrategy = shardStrategyFactory.newShardStrategy(shardIds);
+    setupIdGenerators();
+  }
+
+  /**
+   * Constructs a ShardedSessionFactoryImpl
+   * @param sessionFactoryShardIdMap Mapping of SessionFactories to shard ids.
+   * When using virtual shards, this map associates SessionFactories (physical
+   * shards) with virtual shards (shard ids).  Map cannot be empty.
+   * Map keys cannot be null.  Map values cannot be null or empty.
+   * @param shardStrategyFactory  factory that knows how to create the {@link ShardStrategy}
+   * that will be used for all shard-related operations
+   * @param classesWithoutTopLevelSaveSupport  All classes that cannot be saved
+   * as top-level objects
+   * @param checkAllAssociatedObjectsForDifferentShards  Flag that controls
+   * whether or not we do full cross-shard relationshp checking (very slow)
+   */
+  public ShardedSessionFactoryImpl(
+      Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
+      ShardStrategyFactory shardStrategyFactory,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    this(Lists.newArrayList(Iterables.concat(sessionFactoryShardIdMap.values())),
+        sessionFactoryShardIdMap,
+        shardStrategyFactory,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  /**
+   * Sets the {@link ControlSessionProvider} on id generators that implement the
+   * {@link GeneratorRequiringControlSessionProvider} interface
+   */
+  private void setupIdGenerators() {
+    for(SessionFactoryImplementor sfi : sessionFactories) {
+      for(Object obj : sfi.getAllClassMetadata().values()) {
+        ClassMetadata cmd = (ClassMetadata) obj;
+        EntityPersister ep = sfi.getEntityPersister(cmd.getEntityName());
+        if(ep.getIdentifierGenerator() instanceof GeneratorRequiringControlSessionProvider) {
+          ((GeneratorRequiringControlSessionProvider)ep.getIdentifierGenerator()).setControlSessionProvider(this);
+        }
+      }
+    }
+  }
+  
+  public Map<SessionFactoryImplementor, Set<ShardId>> getSessionFactoryShardIdMap() {
+    return sessionFactoryShardIdMap;
+  }
+
+  /**
+   * Unsupported.  This is a technical decision.  We would need a
+   * ShardedConnection in order to make this work, but since this method is
+   * exposed on the public api we can't force clients to provide it.  And
+   * at any rate, exposing a ShardedConnection somewhat defeats the purpose
+   * of tucking away all the sharding intelligence.
+   */
+  public Session openSession(Connection connection) {
+    throw new UnsupportedOperationException(
+        "Cannot open a sharded session with a user provided connection.");
+  }
+
+  /**
+   * Warning: this interceptor will be shared across all shards, so be very
+   * careful about using a stateful implementation.
+   */
+  public ShardedSession openSession(Interceptor interceptor)
+      throws HibernateException {
+    return new ShardedSessionImpl(
+        interceptor,
+        this,
+        shardStrategy,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  /**
+   * Unsupported.  This is a technical decision.  See {@link ShardedSessionFactoryImpl#openSession(Connection)}
+   * for an explanation.
+   */
+  public Session openSession(Connection connection, Interceptor interceptor) {
+    throw new UnsupportedOperationException(
+        "Cannot open a sharded session with a user provided connection.");
+  }
+
+  public ShardedSession openSession() throws HibernateException {
+    return new ShardedSessionImpl(
+        this,
+        shardStrategy,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  /**
+   * Unsupported.  This is a project decision.  We'll get to it later.
+   */
+  public StatelessSession openStatelessSession() {
+    throw new UnsupportedOperationException("Not yet implemented");
+  }
+
+  /**
+   * Unsupported.  This is a technical decision.  See {@link ShardedSessionFactoryImpl#openSession(Connection)}
+   * for an explanation.
+   */
+  public StatelessSession openStatelessSession(Connection connection) {
+    throw new UnsupportedOperationException(
+        "Cannot open a stateless sharded session with a user provided connection");
+  }
+
+  public Session getCurrentSession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata(Class persistentClass)
+      throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getClassMetadata(persistentClass);
+  }
+
+  public ClassMetadata getClassMetadata(String entityName)
+      throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getClassMetadata(entityName);
+  }
+
+  public CollectionMetadata getCollectionMetadata(String roleName)
+      throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getCollectionMetadata(roleName);
+  }
+
+  public Map getAllClassMetadata() throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getAllClassMetadata();
+  }
+
+  public Map getAllCollectionMetadata() throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getAllCollectionMetadata();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Statistics getStatistics() {
+    return statistics;
+  }
+
+  public void close() throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.close();
+    }
+    sessionFactories.clear();
+    if(classesWithoutTopLevelSaveSupport != null) {
+      classesWithoutTopLevelSaveSupport.clear();
+    }
+    if(sessionFactoryShardIdMap != null) {
+      sessionFactoryShardIdMap.clear();
+    }
+    if(fullSessionFactoryShardIdMap != null) {
+      fullSessionFactoryShardIdMap.clear();
+    }
+    statistics.clear();
+  }
+
+  public boolean isClosed() {
+    // a ShardedSessionFactory is closed if any of its SessionFactories are closed
+    for(SessionFactory sf : sessionFactories) {
+      if(sf.isClosed()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public void evict(Class persistentClass) throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evict(persistentClass);
+    }
+  }
+
+  public void evict(Class persistentClass, Serializable id)
+      throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evict(persistentClass, id);
+    }
+  }
+
+  public void evictEntity(String entityName) throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictEntity(entityName);
+    }
+  }
+
+  public void evictEntity(String entityName, Serializable id)
+      throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictEntity(entityName, id);
+    }
+  }
+
+  public void evictCollection(String roleName) throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictCollection(roleName);
+    }
+  }
+
+  public void evictCollection(String roleName, Serializable id)
+      throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictCollection(roleName, id);
+    }
+  }
+
+  public void evictQueries() throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictQueries();
+    }
+  }
+
+  public void evictQueries(String cacheRegion) throws HibernateException {
+    for(SessionFactory sf : sessionFactories) {
+      sf.evictQueries(cacheRegion);
+    }
+  }
+
+  public Set getDefinedFilterNames() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getDefinedFilterNames();
+  }
+
+  public FilterDefinition getFilterDefinition(String filterName)
+      throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getFilterDefinition(filterName);
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical one.
+   */
+  public Reference getReference() throws NamingException {
+    throw new UnsupportedOperationException(
+        "Sharded session factories do not support References (sorry).");
+  }
+
+  public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
+    // since all configs are same, we return any
+    return getAnyFactory().getIdentifierGenerator(rootEntityName);
+  }
+
+  public SessionImplementor openControlSession() {
+    Preconditions.checkState(controlSessionFactory != null);
+    Session session = controlSessionFactory.openSession();
+    return  (SessionImplementor)session;
+  }
+
+  public boolean containsFactory(SessionFactoryImplementor factory) {
+    return sessionFactories.contains(factory);
+  }
+
+  private SessionFactoryImplementor getAnyFactory() {
+    return sessionFactories.get(0);
+  }
+
+  public List<SessionFactory> getSessionFactories() {
+    return Collections.<SessionFactory>unmodifiableList(sessionFactories);
+  }
+
+  /**
+   * Constructs a ShardedSessionFactory that operates on the given list of
+   * shardIds. This operation is relatively lightweight as the returned
+   * ShardedSessionFactory reuses existing shards. Most common use will be to
+   * provide a ShardedSessionFactory that manages a subset of the application's
+   * shards.
+   *
+   * @param shardIds
+   * @param shardStrategyFactory
+   * @return ShardedSessionFactory
+   */
+  public ShardedSessionFactory getSessionFactory(List<ShardId> shardIds,
+      ShardStrategyFactory shardStrategyFactory) {
+    return new SubsetShardedSessionFactoryImpl(
+        shardIds,
+        fullSessionFactoryShardIdMap,
+        shardStrategyFactory,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  @Override
+  protected void finalize() throws Throwable {
+    try {
+      // try to be helpful to apps that don't clean up properly
+      if(!isClosed()) {
+        log.warn("ShardedSessionFactoryImpl is being garbage collected but it was never properly closed.");
+        try {
+          close();
+        } catch (Exception e) {
+          log.warn("Caught exception trying to close.", e);
+        }
+      }
+    } finally {
+      super.finalize();
+    }
+  }
+
+  public EntityPersister getEntityPersister(String entityName)
+      throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getEntityPersister(entityName);
+  }
+
+  public CollectionPersister getCollectionPersister(String role)
+      throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getCollectionPersister(role);
+  }
+
+  public Dialect getDialect() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getDialect();
+  }
+
+  public Interceptor getInterceptor() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getInterceptor();
+  }
+
+  public QueryPlanCache getQueryPlanCache() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getQueryPlanCache();
+  }
+
+  public Type[] getReturnTypes(String queryString) throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getReturnTypes(queryString);
+  }
+
+  public String[] getReturnAliases(String queryString)
+      throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getReturnAliases(queryString);
+  }
+
+  public ConnectionProvider getConnectionProvider() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getConnectionProvider();
+  }
+
+  public String[] getImplementors(String className) throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getImplementors(className);
+  }
+
+  public String getImportedClassName(String name) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getImportedClassName(name);
+  }
+
+  public TransactionManager getTransactionManager() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getTransactionManager();
+  }
+
+  public QueryCache getQueryCache() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getQueryCache();
+  }
+
+  public QueryCache getQueryCache(String regionName) throws HibernateException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getQueryCache(regionName);
+  }
+
+  public UpdateTimestampsCache getUpdateTimestampsCache() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getUpdateTimestampsCache();
+  }
+
+  public StatisticsImplementor getStatisticsImplementor() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getStatisticsImplementor();
+  }
+
+  public NamedQueryDefinition getNamedQuery(String queryName) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getNamedQuery(queryName);
+  }
+
+  public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getNamedSQLQuery(queryName);
+  }
+
+  public ResultSetMappingDefinition getResultSetMapping(String name) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getResultSetMapping(name);
+  }
+
+  public Cache getSecondLevelCacheRegion(String regionName) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getSecondLevelCacheRegion(regionName);
+  }
+
+  public Map getAllSecondLevelCacheRegions() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getAllSecondLevelCacheRegions();
+  }
+
+  public SQLExceptionConverter getSQLExceptionConverter() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getSQLExceptionConverter();
+  }
+
+  public Settings getSettings() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getSettings();
+  }
+
+  public Session openTemporarySession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a technical decision.  See {@link ShardedSessionFactoryImpl#openSession(Connection)}
+   * for an explanation.
+   */
+  public Session openSession(final Connection connection,
+      final boolean flushBeforeCompletionEnabled,
+      final boolean autoCloseSessionEnabled,
+      final ConnectionReleaseMode connectionReleaseMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set getCollectionRolesByEntityParticipant(String entityName) {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getCollectionRolesByEntityParticipant(entityName);
+  }
+
+  public Type getIdentifierType(String className) throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getIdentifierType(className);
+  }
+
+  public String getIdentifierPropertyName(String className)
+      throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getIdentifierPropertyName(className);
+  }
+
+  public Type getReferencedPropertyType(String className, String propertyName)
+      throws MappingException {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getReferencedPropertyType(className, propertyName);
+  }
+
+  public EntityNotFoundDelegate getEntityNotFoundDelegate() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getEntityNotFoundDelegate();
+  }
+
+  public SQLFunctionRegistry getSqlFunctionRegistry() {
+    // assumption is that all session factories are configured the same way,
+    // so it doesn't matter which session factory answers this question
+    return getAnyFactory().getSqlFunctionRegistry();
+  }
+}
+

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/ShardedSessionImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,1362 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.CrossShardAssociationException;
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.ShardImpl;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.ShardedTransaction;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Sets;
+import org.hibernate.shards.criteria.CriteriaFactoryImpl;
+import org.hibernate.shards.criteria.CriteriaId;
+import org.hibernate.shards.criteria.ShardedCriteriaImpl;
+import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
+import org.hibernate.shards.engine.ShardedSessionImplementor;
+import org.hibernate.shards.id.ShardEncodingIdentifierGenerator;
+import org.hibernate.shards.query.AdHocQueryFactoryImpl;
+import org.hibernate.shards.query.ExitOperationsQueryCollector;
+import org.hibernate.shards.query.NamedQueryFactoryImpl;
+import org.hibernate.shards.query.QueryId;
+import org.hibernate.shards.query.ShardedQueryImpl;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.exit.FirstNonNullResultExitStrategy;
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyDataImpl;
+import org.hibernate.shards.transaction.ShardedTransactionImpl;
+import org.hibernate.shards.util.Iterables;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Pair;
+import org.hibernate.shards.util.Preconditions;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.CacheMode;
+import org.hibernate.Criteria;
+import org.hibernate.EntityMode;
+import org.hibernate.Filter;
+import org.hibernate.FlushMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.LockMode;
+import org.hibernate.Query;
+import org.hibernate.ReplicationMode;
+import org.hibernate.SQLQuery;
+import org.hibernate.SessionException;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.TransientObjectException;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.stat.SessionStatistics;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Concrete implementation of a ShardedSession, and also the central component of
+ * Hibernate Shards' internal implementation. This class exposes two interfaces;
+ * ShardedSession itself, to the application, and ShardedSessionImplementor, to
+ * other components of Hibernate Shards. This class is not threadsafe.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionImpl implements ShardedSession, ShardedSessionImplementor,
+    ShardIdResolver {
+
+  private static ThreadLocal<ShardId> currentSubgraphShardId = new ThreadLocal<ShardId>();
+
+  private final ShardedSessionFactoryImplementor shardedSessionFactory;
+
+  private final List<Shard> shards;
+
+  private final Map<ShardId, Shard> shardIdsToShards;
+
+  private final ShardStrategy shardStrategy;
+
+  private final Set<Class<?>> classesWithoutTopLevelSaveSupport;
+
+  private final boolean checkAllAssociatedObjectsForDifferentShards;
+
+  private ShardedTransaction transaction;
+
+  private boolean closed = false;
+
+  private boolean lockedShard = false;
+
+  private ShardId lockedShardId;
+
+  // access to sharded session is single-threaded so we can use a non-atomic
+  // counter for criteria ids or query ids
+  private int nextCriteriaId = 0;
+  private int nextQueryId = 0;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  /**
+   * Constructor used for openSession(...) processing.
+   *
+   * @param shardedSessionFactory The factory from which this session was obtained
+   * @param shardStrategy The shard strategy for this session
+   * @param classesWithoutTopLevelSaveSupport The set of classes on which top-level save can not be performed
+   * @param checkAllAssociatedObjectsForDifferentShards Should we check for cross-shard relationships
+   */
+  ShardedSessionImpl(
+      ShardedSessionFactoryImplementor shardedSessionFactory,
+      ShardStrategy shardStrategy,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    this(
+        null,
+        shardedSessionFactory,
+        shardStrategy,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  /**
+   * Constructor used for openSession(...) processing.
+   *
+   * @param interceptor The interceptor to be applied to this session
+   * @param shardedSessionFactory The factory from which this session was obtained
+   * @param shardStrategy The shard strategy for this session
+   * @param classesWithoutTopLevelSaveSupport The set of classes on which top-level save can not be performed
+   * @param checkAllAssociatedObjectsForDifferentShards Should we check for cross-shard relationships
+   */
+  ShardedSessionImpl(
+      /*@Nullable*/ Interceptor interceptor,
+      ShardedSessionFactoryImplementor shardedSessionFactory,
+      ShardStrategy shardStrategy,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    this.shardedSessionFactory = shardedSessionFactory;
+    this.shards =
+        buildShardListFromSessionFactoryShardIdMap(
+            shardedSessionFactory.getSessionFactoryShardIdMap(),
+            checkAllAssociatedObjectsForDifferentShards,
+            this,
+            interceptor);
+    this.shardIdsToShards = buildShardIdsToShardsMap();
+    this.shardStrategy = shardStrategy;
+    this.classesWithoutTopLevelSaveSupport = classesWithoutTopLevelSaveSupport;
+    this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;
+  }
+
+  private Map<ShardId, Shard> buildShardIdsToShardsMap() {
+    Map<ShardId, Shard> map = Maps.newHashMap();
+    for(Shard shard : shards) {
+      for(ShardId shardId : shard.getShardIds()) {
+        map.put(shardId, shard);
+      }
+    }
+    return map;
+  }
+
+  static List<Shard> buildShardListFromSessionFactoryShardIdMap(
+      Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
+      boolean checkAllAssociatedObjectsForDifferentShards,
+      ShardIdResolver shardIdResolver,
+      /*@Nullable*/ final Interceptor interceptor) {
+    List<Shard> list = Lists.newArrayList();
+    for(Map.Entry<SessionFactoryImplementor, Set<ShardId>> entry : sessionFactoryShardIdMap.entrySet()) {
+      OpenSessionEvent eventToRegister = null;
+      Interceptor interceptorToSet = interceptor;
+      if(checkAllAssociatedObjectsForDifferentShards) {
+        // cross shard association checks for updates are handled using interceptors
+        CrossShardRelationshipDetectingInterceptor csrdi = new CrossShardRelationshipDetectingInterceptor(shardIdResolver);
+        if(interceptorToSet == null) {
+          // no interceptor to wrap so just use the cross-shard detecting interceptor raw
+          // this is safe because it's a stateless interceptor
+          interceptorToSet = csrdi;
+        } else {
+          // user specified their own interceptor, so wrap it with a decorator
+          // that will still do the cross shard association checks
+          Pair<Interceptor, OpenSessionEvent> result = decorateInterceptor(csrdi, interceptor);
+          interceptorToSet = result.first;
+          eventToRegister = result.second;
+        }
+      } else if(interceptorToSet != null) {
+        // user specified their own interceptor so need to account for the fact
+        // that it might be stateful
+        Pair<Interceptor, OpenSessionEvent> result = handleStatefulInterceptor(interceptorToSet);
+        interceptorToSet = result.first;
+        eventToRegister = result.second;
+      }
+      Shard shard =
+          new ShardImpl(
+              entry.getValue(),
+              entry.getKey(),
+              interceptorToSet);
+      list.add(shard);
+      if(eventToRegister != null) {
+        shard.addOpenSessionEvent(eventToRegister);
+      }
+    }
+    return list;
+  }
+
+  static Pair<Interceptor, OpenSessionEvent> handleStatefulInterceptor(
+      Interceptor mightBeStateful) {
+    OpenSessionEvent openSessionEvent = null;
+    if(mightBeStateful instanceof StatefulInterceptorFactory) {
+      mightBeStateful = ((StatefulInterceptorFactory)mightBeStateful).newInstance();
+      if(mightBeStateful instanceof RequiresSession) {
+        openSessionEvent = new SetSessionOnRequiresSessionEvent((RequiresSession)mightBeStateful);
+      }
+    }
+    return Pair.of(mightBeStateful, openSessionEvent);
+  }
+
+  static Pair<Interceptor, OpenSessionEvent> decorateInterceptor(
+      CrossShardRelationshipDetectingInterceptor csrdi,
+      Interceptor decorateMe) {
+    Pair<Interceptor, OpenSessionEvent> pair = handleStatefulInterceptor(decorateMe);
+    Interceptor decorator = new CrossShardRelationshipDetectingInterceptorDecorator(csrdi, pair.first);
+    return Pair.of(decorator, pair.second);
+  }
+
+  private Object applyGetOperation(
+      ShardOperation<Object> shardOp,
+      ShardResolutionStrategyData srsd) {
+    List<ShardId> shardIds = selectShardIdsFromShardResolutionStrategyData(srsd);
+    return
+      shardStrategy.getShardAccessStrategy().apply(
+          shardIdListToShardList(shardIds),
+          shardOp,
+          new FirstNonNullResultExitStrategy<Object>(),
+          new ExitOperationsQueryCollector());
+  }
+
+  private List<Shard> shardIdListToShardList(List<ShardId> shardIds) {
+    Set<Shard> shards = Sets.newHashSet();
+    for (ShardId shardId : shardIds) {
+      shards.add(shardIdsToShards.get(shardId));
+    }
+    return Lists.newArrayList(shards);
+  }
+
+  public List<Shard> getShards() {
+    return Collections.unmodifiableList(shards);
+  }
+
+  public Object get(final Class clazz, final Serializable id) throws HibernateException {
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        return shard.get(clazz, id);
+      }
+
+      public String getOperationName() {
+        return "get(Class class, Serializable id)";
+      }
+    };
+    return applyGetOperation(shardOp, new ShardResolutionStrategyDataImpl(clazz, id));
+  }
+
+  public Object get(final Class clazz, final Serializable id, final LockMode lockMode)
+      throws HibernateException {
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        return shard.get(clazz, id, lockMode);
+      }
+
+      public String getOperationName() {
+        return "get(Class class, Serializable id, LockMode lockMode)";
+      }
+    };
+    // we're not letting people customize shard selection by lockMode
+    return applyGetOperation(shardOp, new ShardResolutionStrategyDataImpl(clazz, id));
+  }
+
+  public Object get(final String entityName, final Serializable id)
+      throws HibernateException {
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        return shard.get(entityName, id);
+      }
+
+      public String getOperationName() {
+        return "get(String entityName, Serializable id)";
+      }
+    };
+    return applyGetOperation(shardOp, new ShardResolutionStrategyDataImpl(entityName, id));
+  }
+
+  public Object get(final String entityName, final Serializable id, final LockMode lockMode)
+      throws HibernateException {
+    ShardOperation<Object> shardOp = new ShardOperation<Object>() {
+      public Object execute(Shard shard) {
+        return shard.get(entityName, id, lockMode);
+      }
+
+      public String getOperationName() {
+        return "get(String entityName, Serializable id, LockMode lockMode)";
+      }
+
+    };
+    // we're not letting people customize shard selection by lockMode
+    return applyGetOperation(shardOp, new ShardResolutionStrategyDataImpl(entityName, id));
+  }
+
+  private Session getSomeSession() {
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        return shard.getSession();
+      }
+    }
+    return null;
+  }
+
+  public EntityMode getEntityMode() {
+    // assume they all have the same EntityMode
+    Session someSession = getSomeSession();
+    if (someSession == null) {
+      someSession = shards.get(0).establishSession();
+    }
+    return someSession.getEntityMode();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Session getSession(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void flush() throws HibernateException {
+    for (Shard shard : shards) {
+      // unopened sessions won't have anything to flush
+      if (shard.getSession() != null) {
+        shard.getSession().flush();
+      }
+    }
+  }
+
+  public void setFlushMode(FlushMode flushMode) {
+    SetFlushModeOpenSessionEvent event = new SetFlushModeOpenSessionEvent(
+        flushMode);
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().setFlushMode(flushMode);
+      } else {
+        shard.addOpenSessionEvent(event);
+      }
+    }
+  }
+
+  public FlushMode getFlushMode() {
+    // all shards must have the same flush mode
+    Session someSession = getSomeSession();
+    if (someSession == null) {
+      someSession = shards.get(0).establishSession();
+    }
+    return someSession.getFlushMode();
+  }
+
+  public void setCacheMode(CacheMode cacheMode) {
+    SetCacheModeOpenSessionEvent event = new SetCacheModeOpenSessionEvent(
+        cacheMode);
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().setCacheMode(cacheMode);
+      } else {
+        shard.addOpenSessionEvent(event);
+      }
+    }
+  }
+
+  public CacheMode getCacheMode() {
+    // all shards must have the same cache mode
+    Session someSession = getSomeSession();
+    if (someSession == null) {
+      someSession = shards.get(0).establishSession();
+    }
+    return someSession.getCacheMode();
+  }
+
+  public SessionFactory getSessionFactory() {
+    return shardedSessionFactory;
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Connection connection() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection close() throws HibernateException {
+    List<Throwable> thrown = null;
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        try {
+          shard.getSession().close();
+        } catch (Throwable t) {
+          if (thrown == null) {
+            thrown = Lists.newArrayList();
+          }
+          thrown.add(t);
+          // we're going to try and close everything that was
+          // opened
+        }
+      }
+    }
+    shards.clear();
+
+    shardIdsToShards.clear();
+
+    classesWithoutTopLevelSaveSupport.clear();
+
+    if (thrown != null && !thrown.isEmpty()) {
+      // we'll just throw the first one
+      Throwable first = thrown.get(0);
+      if (HibernateException.class.isAssignableFrom(first.getClass())) {
+        throw (HibernateException)first;
+      }
+      throw new HibernateException(first);
+    }
+    closed = true;
+    // TODO(maxr) what should I return here?
+    return null;
+  }
+
+  public void cancelQuery() throws HibernateException {
+    // cancel across all shards
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().cancelQuery();
+      }
+    }
+  }
+
+  public boolean isOpen() {
+    // one open session means the sharded session is open
+    for (Shard shard : shards) {
+      if (shard.getSession() != null && shard.getSession().isOpen()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public boolean isConnected() {
+    // one connected shard means the session as a whole is connected
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        if (shard.getSession().isConnected()) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public boolean isDirty() throws HibernateException {
+    // one dirty shard is all it takes
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        if (shard.getSession().isDirty()) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public Serializable getIdentifier(Object object) throws HibernateException {
+
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        try {
+          return shard.getSession().getIdentifier(object);
+        } catch(TransientObjectException e) {
+          // Object is transient or is not associated with this session.
+        }
+      }
+    }
+    throw new TransientObjectException("Instance is transient or associated with a defferent Session");
+  }
+
+  public boolean contains(Object object) {
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        if (shard.getSession().contains(object)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  public void evict(Object object) throws HibernateException {
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().evict(object);
+      }
+    }
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object load(Class theClass, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object load(String entityName, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object load(Class theClass, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object load(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void load(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void replicate(Object object, ReplicationMode replicationMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void replicate(String entityName, Object object,
+      ReplicationMode replicationMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(String entityName, Object object) throws HibernateException {
+    ShardId shardId;
+    if(contains(object)) {
+      shardId = getShardIdForObject(object);
+    } else {
+      shardId = selectShardIdForNewObject(object);
+    }
+    Preconditions.checkNotNull(shardId);
+    setCurrentSubgraphShardId(shardId);
+    log.debug(String.format("Saving object of type %s to shard %s", object.getClass(), shardId));
+     return shardIdsToShards.get(shardId).save(entityName, object);
+  }
+
+  ShardId selectShardIdForNewObject(Object obj) {
+    if(lockedShardId != null) {
+      return lockedShardId;
+    }
+    ShardId shardId;
+    /*
+     * Someone is trying to save this object, and that's wonderful, but if
+     * this object references or is referenced by any other objects that have already been
+     * associated with a session it's important that this object end up
+     * associated with the same session.  In order to make sure that happens,
+     * we're going to look at the metadata for this object and see what
+     * references we have, and then use those to determine the proper shard.
+     * If we can't find any references we'll leave it up to the shard selection
+     * strategy.
+     */
+    shardId = getShardIdOfRelatedObject(obj);
+    if(shardId == null) {
+      checkForUnsupportedTopLevelSave(obj.getClass());
+      shardId = shardStrategy.getShardSelectionStrategy().selectShardIdForNewObject(obj);
+    }
+    // lock has been requested but shard has not yet been selected - lock it in
+    if(lockedShard) {
+      lockedShardId = shardId;
+    }
+    log.debug(String.format("Selected shard %d for object of type %s", shardId.getId(), obj.getClass().getName()));
+    return shardId;
+  }
+
+  /*
+   * We already know that we don't have a shardId locked in for this session,
+   * and we already know that this object can't grab its session from some
+   * other object (we looked).  If this class is in the set of classes
+   * that don't support top-level saves, it's an error.
+   * This is to prevent clients from accidentally splitting their object graphs
+   * across multiple shards.
+   */
+  private void checkForUnsupportedTopLevelSave(Class<?> clazz) {
+    if(classesWithoutTopLevelSaveSupport.contains(clazz)) {
+      final String msg = String.format(
+          "Attempt to save object of type %s as a top-level object.",
+          clazz.getName());
+      log.error(msg);
+      throw new HibernateException(msg);
+    }
+  }
+
+  /**
+   * TODO(maxr) I can see this method benefitting from a cache that lets us quickly
+   * see which properties we might need to look at.
+   */
+  ShardId getShardIdOfRelatedObject(Object obj) {
+    ClassMetadata cmd = getClassMetadata(obj.getClass());
+    Type[] types = cmd.getPropertyTypes();
+    // TODO(maxr) fix hard-coded entity mode
+    Object[] values = cmd.getPropertyValues(obj, EntityMode.POJO);
+    ShardId shardId = null;
+    List<Collection<Object>> collections = null;
+    for(Pair<Type, Object> pair : CrossShardRelationshipDetectingInterceptor.buildListOfAssociations(types, values)) {
+      if(pair.getFirst().isCollectionType()) {
+        /**
+         * collection types are more expensive to evaluate (might involve
+         * lazy-loading the contents of the collection from the db), so
+         * let's hold off until the end on the chance that we can fail
+         * quickly.
+         */
+        if(collections == null) {
+          collections = Lists.newArrayList();
+        }
+        collections.add((Collection<Object>) pair.getSecond());
+      } else {
+        shardId = checkForConflictingShardId(shardId, obj.getClass(), pair.getSecond());
+        /**
+         * if we're not checking for different shards, return as soon as we've
+         * got one
+         */
+        if(shardId != null && !checkAllAssociatedObjectsForDifferentShards) {
+          return shardId;
+        }
+      }
+    }
+    if(collections != null) {
+      for(Object collEntry : Iterables.concat(collections)) {
+        shardId = checkForConflictingShardId(shardId, obj.getClass(), collEntry);
+        if(shardId != null && !checkAllAssociatedObjectsForDifferentShards) {
+          /**
+           * if we're not checking for different shards, return as soon as we've
+           * got one
+           */
+          return shardId;
+        }
+      }
+    }
+    return shardId;
+  }
+
+  ShardId checkForConflictingShardId(ShardId existingShardId, Class<?> newObjectClass, Object associatedObject) {
+    ShardId localShardId = getShardIdForObject(associatedObject);
+    if(localShardId != null) {
+      if(existingShardId == null) {
+        existingShardId = localShardId;
+      } else if(!localShardId.equals(existingShardId)) {
+        final String msg = String.format(
+            "Object of type %s is on shard %d but an associated object of type %s is on shard %d.",
+            newObjectClass.getName(),
+            existingShardId.getId(),
+            associatedObject.getClass().getName(),
+            localShardId.getId());
+        log.error(msg);
+        throw new CrossShardAssociationException(msg);
+      }
+    }
+    return existingShardId;
+  }
+
+  ClassMetadata getClassMetadata(Class<?> clazz) {
+    return getSessionFactory().getClassMetadata(clazz);
+  }
+
+  public Serializable save(Object object)
+      throws HibernateException {
+    return save(null, object);
+  }
+
+  public void saveOrUpdate(Object object) throws HibernateException {
+    applySaveOrUpdateOperation(SAVE_OR_UPDATE_SIMPLE, object);
+  }
+
+  public void saveOrUpdate(final String entityName, Object object)
+      throws HibernateException {
+    SaveOrUpdateOperation op = new SaveOrUpdateOperation() {
+      public void saveOrUpdate(Shard shard, Object object) {
+        shard.saveOrUpdate(entityName, object);
+      }
+
+      public void update(Shard shard, Object object) {
+        shard.update(entityName, object);
+      }
+    };
+    applySaveOrUpdateOperation(op, object);
+  }
+
+  void applySaveOrUpdateOperation(SaveOrUpdateOperation op, Object object) {
+    List<ShardId> saveOrUpdateShardIds = determineShardIdsForObjectThatMightAlreadyExist(object);
+    if(saveOrUpdateShardIds.size() == 1) {
+      /**
+       * if there's only 1 shard id we don't need to worry about whether this is
+       * a save or an update because we know we've got the right shard.
+       * We'll let that shard figure out what the right thing to do is
+       */
+      ShardId shardId = saveOrUpdateShardIds.get(0);
+      setCurrentSubgraphShardId(shardId);
+      op.saveOrUpdate(shardIdsToShards.get(shardId), object);
+    } else {
+      /**
+       * If we've got multiple shard ids we know it's an update.  However,
+       * we can't call saveOrUpdate() on multiple shards because if it
+       * already exists and we call saveOrUpdate() on the wrong shard we're
+       * going to end up with the same object in multiple shards, and that's
+       * really bad.  Instead we'll just figure out the single shard on which
+       * the object resides and perform the update there.
+       */
+      ShardId shardId = getShardIdForObject(object);
+      setCurrentSubgraphShardId(shardId);
+      Shard shard = shardIdsToShards.get(shardId);
+      op.update(shard, object);
+    }
+  }
+
+  List<ShardId> determineShardIdsForObjectThatMightAlreadyExist(Object object) {
+    Serializable id = extractId(object);
+    if(id == null) {
+      ShardId shardId = selectShardIdForNewObject(object);
+      // if there's no id then it's clearly a save operation
+      return Collections.singletonList(shardId);
+    }
+    /**
+     * there is an id so it might be a save operation (user provided the id)
+     * or it might be an update
+     */
+    ShardResolutionStrategyData srsd = new ShardResolutionStrategyDataImpl(object.getClass(), id);
+    return selectShardIdsFromShardResolutionStrategyData(srsd);
+  }
+
+  private Serializable extractId(Object object) {
+    ClassMetadata cmd = shardedSessionFactory.getClassMetadata(object.getClass());
+    // I'm just guessing about the EntityMode
+    return cmd.getIdentifier(object, EntityMode.POJO);
+  }
+
+  public void update(Object object) throws HibernateException {
+    /*
+     * we might get back multiple shards if there isn't a sure-fire
+     * way to derive the shard from the object, but since the object
+     * only exists on one shard there's no harm in trying to update
+     * it multiple places because the update will only succeed in one place.
+     */
+    // What about exceptions?
+    for(Shard shard : determineShardsForObjectThatExists(object)) {
+      shard.update(object);
+    }
+  }
+
+  public void update(String entityName, Object object)
+      throws HibernateException {
+    for(Shard shard : determineShardsForObjectThatExists(object)) {
+      shard.update(entityName, object);
+    }
+  }
+
+  private List<Shard> determineShardsForObjectThatExists(Object object) {
+    Serializable id = extractId(object);
+    ShardResolutionStrategyData srsd = new ShardResolutionStrategyDataImpl(object.getClass(), id);
+    List<ShardId> shardIds = selectShardIdsFromShardResolutionStrategyData(srsd);
+    return shardIdListToShardList(shardIds);
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object merge(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Object merge(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void persist(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void persist(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(Object object) throws HibernateException {
+    /**
+     * we might get back multiple shards if there isn't a sure-fire
+     * way to derive the shard from the object.  It turns out that if you have an
+     * object associated with Session x and you try to delete that object in
+     * Sessoin y, and if that object has persistent collections, Hibernate will
+     * blow up because it will try to associate the persistent collection with
+     * a different Session as part of the cascade.  In order to avoid this we
+     * need to be precise about the shard on which we perform the delete
+     */
+
+    // What about exceptions?
+    List<Shard> potentialShards = determineShardsForObjectThatExists(object);
+    if(potentialShards.size() == 1) {
+      potentialShards.get(0).delete(object);
+      return;
+    }
+    ShardId shardId = getShardIdForObject(object, potentialShards);
+    shardIdsToShards.get(shardId).delete(object);
+  }
+
+  public void delete(String entityName, Object object)
+      throws HibernateException {
+    for(Shard shard : determineShardsForObjectThatExists(object)) {
+      shard.delete(entityName, object);
+    }
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void lock(Object object, LockMode lockMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void lock(String entityName, Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void refresh(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void refresh(Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public LockMode getCurrentLockMode(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Transaction beginTransaction() throws HibernateException {
+    errorIfClosed();
+    Transaction result = getTransaction();
+    result.begin();
+    return result;
+  }
+
+  public Transaction getTransaction() {
+    errorIfClosed();
+    if (transaction == null) {
+      transaction = new ShardedTransactionImpl(this);
+    }
+    return transaction;
+  }
+
+  public Criteria createCriteria(Class persistentClass) {
+    return new ShardedCriteriaImpl(
+        new CriteriaId(nextCriteriaId++),
+        shards,
+        new CriteriaFactoryImpl(persistentClass),
+        shardStrategy.getShardAccessStrategy());
+  }
+
+  public Criteria createCriteria(Class persistentClass, String alias) {
+    return new ShardedCriteriaImpl(
+        new CriteriaId(nextCriteriaId++),
+        shards,
+        new CriteriaFactoryImpl(persistentClass, alias),
+        shardStrategy.getShardAccessStrategy());
+  }
+
+  public Criteria createCriteria(String entityName) {
+    return new ShardedCriteriaImpl(
+        new CriteriaId(nextCriteriaId++),
+        shards,
+        new CriteriaFactoryImpl(entityName),
+        shardStrategy.getShardAccessStrategy());
+  }
+
+  public Criteria createCriteria(String entityName, String alias) {
+    return new ShardedCriteriaImpl(
+        new CriteriaId(nextCriteriaId++),
+        shards,
+        new CriteriaFactoryImpl(entityName, alias),
+        shardStrategy.getShardAccessStrategy());
+  }
+
+  public Query createQuery(String queryString) throws HibernateException {
+    return new ShardedQueryImpl(new QueryId(nextQueryId++),
+            shards,
+            new AdHocQueryFactoryImpl(queryString),
+            shardStrategy.getShardAccessStrategy());
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public SQLQuery createSQLQuery(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Query createFilter(Object collection, String queryString)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getNamedQuery(String queryName) throws HibernateException {
+
+    return new ShardedQueryImpl(new QueryId(nextQueryId++),
+            shards,
+            new NamedQueryFactoryImpl(queryName),
+            shardStrategy.getShardAccessStrategy());
+  }
+
+  public void clear() {
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().clear();
+      }
+    }
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public String getEntityName(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Filter enableFilter(String filterName) {
+    EnableFilterOpenSessionEvent event = new EnableFilterOpenSessionEvent(
+        filterName);
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().enableFilter(filterName);
+      } else {
+        shard.addOpenSessionEvent(event);
+      }
+    }
+    // TODO(maxr) what do we return here?  A sharded filter?
+    return null;
+  }
+
+  public Filter getEnabledFilter(String filterName) {
+    // all session have same filters
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        Filter filter = shard.getSession().getEnabledFilter(filterName);
+        if (filter != null) {
+          return filter;
+        }
+      }
+    }
+    // TODO(maxr) what do we return here?
+    return null;
+  }
+
+  public void disableFilter(String filterName) {
+    DisableFilterOpenSessionEvent event = new DisableFilterOpenSessionEvent(
+        filterName);
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().disableFilter(filterName);
+      } else {
+        shard.addOpenSessionEvent(event);
+      }
+    }
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public SessionStatistics getStatistics() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setReadOnly(Object entity, boolean readOnly) {
+    SetReadOnlyOpenSessionEvent event = new SetReadOnlyOpenSessionEvent(entity,
+        readOnly);
+    for (Shard shard : shards) {
+      if (shard.getSession() != null) {
+        shard.getSession().setReadOnly(entity, readOnly);
+      } else {
+        shard.addOpenSessionEvent(event);
+      }
+    }
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public Connection disconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a scope decision, not a technical decision.
+   */
+  public void reconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * Unsupported.  This is a technical decision.
+   */
+  public void reconnect(Connection connection) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * All methods below fulfill the org.hibernate.classic.Session interface.
+   * These methods are all deprecated, and since we don't really have any
+   * legacy Hibernate code at Google so we're simply not going to support them.
+   */
+
+  /**
+   * @deprecated
+   */
+  public Object saveOrUpdateCopy(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Object saveOrUpdateCopy(Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Object saveOrUpdateCopy(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Object saveOrUpdateCopy(String entityName, Object object,
+      Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public List find(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public List find(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public List find(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Iterator iterate(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Iterator iterate(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Iterator iterate(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Collection filter(Object collection, String filter)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Collection filter(Object collection, String filter, Object value,
+      Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Collection filter(Object collection, String filter, Object[] values,
+      Type[] types) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public int delete(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public int delete(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public int delete(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Query createSQLQuery(String sql, String returnAlias,
+      Class returnClass) {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public Query createSQLQuery(String sql, String[] returnAliases,
+      Class[] returnClasses) {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public void save(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public void save(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public void update(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  /**
+   * @deprecated
+   */
+  public void update(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  void errorIfClosed() {
+    if (closed) {
+      throw new SessionException( "Session is closed!" );
+    }
+  }
+
+  interface SaveOrUpdateOperation {
+    void saveOrUpdate(Shard shard, Object object);
+    void update(Shard shard, Object object);
+  }
+
+  private static final SaveOrUpdateOperation SAVE_OR_UPDATE_SIMPLE = new SaveOrUpdateOperation() {
+    public void saveOrUpdate(Shard shard, Object object) {
+      shard.saveOrUpdate(object);
+    }
+
+    public void update(Shard shard, Object object) {
+      shard.update(object);
+    }
+  };
+
+  private Shard getShardForObject(Object obj, List<Shard> shardsToConsider) {
+    for(Shard shard : shardsToConsider) {
+      if(shard.getSession() != null && shard.getSession().contains(obj)) {
+        return shard;
+      }
+    }
+    return null;
+  }
+
+  private Session getSessionForObject(Object obj, List<Shard> shardsToConsider) {
+    Shard shard = getShardForObject(obj, shardsToConsider);
+    if(shard == null) {
+      return null;
+    }
+    return shard.getSession();
+  }
+
+  public Session getSessionForObject(Object obj) {
+    return getSessionForObject(obj, shards);
+  }
+
+  public ShardId getShardIdForObject(Object obj, List<Shard> shardsToConsider) {
+    Shard shard = getShardForObject(obj, shardsToConsider);
+    if(shard == null) {
+      return null;
+    } else if (shard.getShardIds().size() == 1) {
+      return shard.getShardIds().iterator().next();
+    } else {
+      String className;
+      if (obj instanceof HibernateProxy) {
+        className = ((HibernateProxy)obj).getHibernateLazyInitializer().getPersistentClass().getName();
+      } else {
+        className = obj.getClass().getName();
+      }
+      IdentifierGenerator idGenerator = shard.getSessionFactoryImplementor().getIdentifierGenerator(className);
+      if (idGenerator instanceof ShardEncodingIdentifierGenerator) {
+        return ((ShardEncodingIdentifierGenerator)idGenerator).extractShardId(getIdentifier(obj));
+      } else {
+        // TODO(tomislav): also use shard resolution strategy if it returns only 1 shard; throw this error in config instead of here
+        throw new HibernateException("Can not use virtual sharding with non-shard resolving id gen");
+      }
+    }
+  }
+
+  public ShardId getShardIdForObject(Object obj) {
+    return getShardIdForObject(obj, shards);
+  }
+
+  List<ShardId> selectShardIdsFromShardResolutionStrategyData(ShardResolutionStrategyData srsd) {
+    IdentifierGenerator idGenerator = shardedSessionFactory.getIdentifierGenerator(srsd.getEntityName());
+    if (idGenerator instanceof ShardEncodingIdentifierGenerator) {
+      return Collections.singletonList(((ShardEncodingIdentifierGenerator)idGenerator).extractShardId(srsd.getId()));
+    }
+    return shardStrategy.getShardResolutionStrategy().selectShardIdsFromShardResolutionStrategyData(srsd);
+  }
+
+  public void lockShard() {
+    lockedShard = true;
+  }
+
+  public boolean getCheckAllAssociatedObjectsForDifferentShards() {
+    return checkAllAssociatedObjectsForDifferentShards;
+  }
+
+  @Override
+  protected void finalize() throws Throwable {
+    try {
+      if(!closed) {
+        log.warn("ShardedSessionImpl is being garbage collected but it was never properly closed.");
+        try {
+          close();
+        } catch (Exception e) {
+          log.warn("Caught exception trying to close.", e);
+        }
+      }
+    } finally {
+      super.finalize();
+    }
+  }
+
+  public static ShardId getCurrentSubgraphShardId() {
+    return currentSubgraphShardId.get();
+  }
+
+  public static void setCurrentSubgraphShardId(ShardId shardId) {
+    currentSubgraphShardId.set(shardId);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/StatefulInterceptorFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/StatefulInterceptorFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/StatefulInterceptorFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Interceptor;
+
+/**
+ * Interface describing an object that knows how to create Interceptors.
+ * Technically this is just an interceptor factory, but it is designed
+ * to be used by clients who want to use stateful interceptors in conjunction
+ * with sharded sessions.  Clients should make sure their Interceptor
+ * implementation implements this interface.  Furthermore, if the
+ * Interceptor implementation requires a reference to the Session, the
+ * Interceptor returned by newInstance() should implement the {@link RequiresSession}
+ * interface.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface StatefulInterceptorFactory {
+  Interceptor newInstance();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SubsetShardedSessionFactoryImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SubsetShardedSessionFactoryImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/session/SubsetShardedSessionFactoryImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.HibernateException;
+
+import java.util.List;
+import java.util.Set;
+import java.util.Map;
+
+/**
+ * This class extends ShardedSessionFactoryImpl and is constructed by supplying
+ * a subset of shardIds that are primarily owned by a ShardedSessionFactoryImpl.
+ * The purpose of this class is to override the .close() method in order to
+ * prevent the SubsetShardedSessionFactoryImpl from closing any session
+ * factories that belong to a ShardedSessionFactoryImpl.
+ *
+ * @author maulik at google.com (Maulik Shah)@google.com (Maulik Shah)
+ */
+public class SubsetShardedSessionFactoryImpl extends ShardedSessionFactoryImpl {
+
+  public SubsetShardedSessionFactoryImpl(List<ShardId> shardIds,
+      Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
+      ShardStrategyFactory shardStrategyFactory,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    super(shardIds, sessionFactoryShardIdMap, shardStrategyFactory,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  protected SubsetShardedSessionFactoryImpl(
+      Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
+      ShardStrategyFactory shardStrategyFactory,
+      Set<Class<?>> classesWithoutTopLevelSaveSupport,
+      boolean checkAllAssociatedObjectsForDifferentShards) {
+    super(sessionFactoryShardIdMap, shardStrategyFactory,
+        classesWithoutTopLevelSaveSupport,
+        checkAllAssociatedObjectsForDifferentShards);
+  }
+
+  /**
+   * This method is a NO-OP. As a ShardedSessionFactoryImpl that represents
+   * a subset of the application's shards, it will not close any shard's
+   * sessionFactory.
+   *
+   * @throws HibernateException
+   */
+  @Override
+  public void close() throws HibernateException {
+    // no-op: this class should never close session factories
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy;
+
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardStrategy {
+
+  ShardSelectionStrategy getShardSelectionStrategy();
+
+  ShardResolutionStrategy getShardResolutionStrategy();
+
+  ShardAccessStrategy getShardAccessStrategy();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy;
+
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardStrategyFactory {
+  ShardStrategy newShardStrategy(List<ShardId> shardIds);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/ShardStrategyImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy;
+
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+import org.hibernate.shards.util.Preconditions;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardStrategyImpl implements ShardStrategy {
+
+  private final ShardSelectionStrategy shardSelectionStrategy;
+  private final ShardResolutionStrategy shardResolutionStrategy;
+  private final ShardAccessStrategy shardAccessStrategy;
+
+  public ShardStrategyImpl(
+      ShardSelectionStrategy shardSelectionStrategy,
+      ShardResolutionStrategy shardResolutionStrategy,
+      ShardAccessStrategy shardAccessStrategy) {
+    Preconditions.checkNotNull(shardSelectionStrategy);
+    Preconditions.checkNotNull(shardResolutionStrategy);
+    Preconditions.checkNotNull(shardAccessStrategy);
+    this.shardSelectionStrategy = shardSelectionStrategy;
+    this.shardResolutionStrategy = shardResolutionStrategy;
+    this.shardAccessStrategy = shardAccessStrategy;
+  }
+
+  public ShardSelectionStrategy getShardSelectionStrategy() {
+    return shardSelectionStrategy;
+  }
+
+  public ShardResolutionStrategy getShardResolutionStrategy() {
+    return shardResolutionStrategy;
+  }
+
+  public ShardAccessStrategy getShardAccessStrategy() {
+    return shardAccessStrategy;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/LoadBalancedSequentialShardAccessStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/LoadBalancedSequentialShardAccessStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/LoadBalancedSequentialShardAccessStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.util.Iterables;
+
+import java.util.Random;
+import java.util.List;
+
+/**
+ * A SequentialShardAccessStrategy starts with the first Shard in the list
+ * every time.  If the ExitStrategy with which the AccessStrategy is paired
+ * supports early exit (keep searching until you have 100 results), the first
+ * shard in the list may receive a disproportionately high percentage of the
+ * queries.  In order to combat this we have a load balanced approach that
+ * adjusts that provides a rotated view of the list of shards.  The list is
+ * rotated by a different amount each time.  The amount by which we rotate
+ * is random because doing a true round-robin would require that we know
+ * the shards we're rotating in advance, but the shards passed to a
+ * ShardAccessStrategy can vary between invocations.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class LoadBalancedSequentialShardAccessStrategy extends SequentialShardAccessStrategy {
+
+  private final Random rand;
+
+  public LoadBalancedSequentialShardAccessStrategy() {
+    this.rand = new Random(System.currentTimeMillis());
+  }
+
+  @Override
+  protected Iterable<Shard> getNextOrderingOfShards(List<Shard> shards) {
+    return Iterables.rotate(shards, rand.nextInt() % shards.size());
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardAccessStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardAccessStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardAccessStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+import org.hibernate.shards.util.Preconditions;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Invokes the given operation on the given shards in parallel.
+ * TODO(maxr) Add support for rejected tasks
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ParallelShardAccessStrategy implements ShardAccessStrategy {
+
+  private final ThreadPoolExecutor executor;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public ParallelShardAccessStrategy(ThreadPoolExecutor executor) {
+    Preconditions.checkNotNull(executor);
+    this.executor = executor;
+  }
+
+  public <T> T apply(
+      List<Shard> shards,
+      ShardOperation<T> operation,
+      ExitStrategy<T> exitStrategy,
+      ExitOperationsCollector exitOperationsCollector) {
+
+    List<StartAwareFutureTask> tasks = Lists.newArrayListWithCapacity(shards.size());
+
+    int taskId = 0;
+
+    /**
+     * Used to prevent threads for processing until all tasks have been
+     * submitted, otherwise we risk tasks that want to cancel other tasks
+     * that have not yet been scheduled.
+     */
+    CountDownLatch startSignal = new CountDownLatch(1);
+    /**
+     * Used to signal this thread that all processing is complete
+     */
+    CountDownLatch doneSignal = new CountDownLatch(shards.size());
+    for(final Shard shard : shards) {
+      // create a task for each shard
+      ParallelShardOperationCallable<T> callable =
+          new ParallelShardOperationCallable<T>(
+              startSignal,
+              doneSignal,
+              exitStrategy,
+              operation,
+              shard,
+              tasks);
+      // wrap the task in a StartAwareFutureTask so that the task can be cancelled
+      StartAwareFutureTask ft = new StartAwareFutureTask(callable, taskId++);
+      tasks.add(ft);
+      // hand the task off to the executor for execution
+      executor.execute(ft);
+    }
+    // the tasks List is populated, release the threads!
+    startSignal.countDown();
+    try {
+      log.debug("Waiting for threads to complete processing before proceeding.");
+      //TODO(maxr) let users customize timeout behavior
+      /*
+      if(!doneSignal.await(10, TimeUnit.SECONDS)) {
+        final String msg = "Parallel operations timed out.";
+        log.error(msg);
+        throw new HibernateException(msg);
+      }
+      */
+      // now we wait until all threads finish
+      doneSignal.await();
+    } catch (InterruptedException e) {
+      // not sure why this would happen or what we should do if it does
+      log.error("Received unexpected exception while waiting for done signal.", e);
+    }
+    log.debug("Compiling results.");
+    return exitStrategy.compileResults(exitOperationsCollector);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardOperationCallable.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardOperationCallable.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ParallelShardOperationCallable.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,137 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Runs a single operation on a single shard, collecting the result of the
+ * operation with an ExitStrategy.  The interesting bit here is that
+ * if the ExitStrategy indicates that there is no more work to be performed,
+ * this object has the ability to cancel the work being performed by all the
+ * other threads.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+class ParallelShardOperationCallable<T> implements Callable<Void> {
+
+  private static final boolean INTERRUPT_IF_RUNNING = false;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  private final CountDownLatch startSignal;
+
+  private final CountDownLatch doneSignal;
+
+  private final ExitStrategy<T> exitStrategy;
+
+  private final ShardOperation<T> operation;
+
+  private final Shard shard;
+
+  private final List<StartAwareFutureTask> futureTasks;
+
+  public ParallelShardOperationCallable(
+      CountDownLatch startSignal,
+      CountDownLatch doneSignal,
+      ExitStrategy<T> exitStrategy,
+      ShardOperation<T> operation,
+      Shard shard,
+      List<StartAwareFutureTask> futureTasks) {
+    this.startSignal = startSignal;
+    this.doneSignal = doneSignal;
+    this.exitStrategy = exitStrategy;
+    this.operation = operation;
+    this.shard = shard;
+    this.futureTasks = futureTasks;
+  }
+
+  public Void call() throws Exception {
+    try {
+      waitForStartSignal();
+      log.debug(String.format("Starting execution of %s against shard %s",  operation.getOperationName(), shard));
+      /**
+       * If addResult() returns true it means there is no more work to be
+       * performed.  Cancel all the outstanding tasks.
+       */
+      if(exitStrategy.addResult(operation.execute(shard), shard)) {
+        log.debug(
+            String.format(
+                "Short-circuiting execution of %s on other threads after execution against shard %s",
+                operation.getOperationName(),
+                shard));
+        /**
+         * It's ok to cancel ourselves because StartAwareFutureTask.cancel()
+         * will return false if a task has already started executing, and we're
+         * already executing.
+         */
+
+        log.debug(String.format("Checking %d future tasks to see if they need to be cancelled.", futureTasks.size()));
+        for(StartAwareFutureTask ft : futureTasks) {
+          log.debug(String.format("Preparing to cancel future task %d.", ft.getId()));
+          /**
+           * If a task was successfully cancelled that means it had not yet
+           * started running.  Since the task won't run, the task won't be
+           * able to decrement the CountDownLatch.  We need to decrement
+           * it on behalf of the cancelled task.
+           */
+          if(ft.cancel(INTERRUPT_IF_RUNNING)) {
+            log.debug("Task cancel returned true, decrementing counter on its behalf.");
+            doneSignal.countDown();
+          } else {
+            log.debug("Task cancel returned false, not decrementing counter on its behalf.");
+          }
+        }
+      } else {
+        log.debug(
+            String.format(
+                "No need to short-cirtcuit execution of %s on other threads after execution against shard %s",
+                operation.getOperationName(),
+                shard));
+      }
+    } finally {
+      // counter must get decremented no matter what
+      log.debug(String.format("Decrementing counter for operation %s on shard %s", operation.getOperationName(), shard));
+      doneSignal.countDown();
+    }
+    return null;
+  }
+
+  private void waitForStartSignal() {
+    try {
+      startSignal.await();
+    } catch (InterruptedException e) {
+      // I see no reason why this should happen
+      final String msg = String.format("Received interrupt while waiting to begin execution of %s against shard %s", operation.getOperationName(), shard);
+      log.error(msg);
+      throw new HibernateException(msg);
+    }
+  }
+}
+

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/SequentialShardAccessStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/SequentialShardAccessStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/SequentialShardAccessStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SequentialShardAccessStrategy implements ShardAccessStrategy {
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public <T> T apply(List<Shard> shards, ShardOperation<T> operation, ExitStrategy<T> exitStrategy, ExitOperationsCollector exitOperationsCollector) {
+    for(Shard shard : getNextOrderingOfShards(shards)) {
+      if(exitStrategy.addResult(operation.execute(shard), null)) {
+        log.debug(
+            String.format(
+                "Short-circuiting operation %s after execution against shard %s",
+                operation.getOperationName(),
+                shard));
+        break;
+      }
+    }
+    return exitStrategy.compileResults(exitOperationsCollector);
+  }
+
+  /**
+   * Override this method if you want to control the order in which the
+   * shards are operated on (this comes in handy when paired with exit
+   * strategies that allow early exit because it allows you to evenly
+   * distribute load).  Deafult implementation is to just iterate in the
+   * same order every time.
+   * @param shards The shards we might want to reorder
+   * @return Reordered view of the shards.
+   */
+  protected Iterable<Shard> getNextOrderingOfShards(List<Shard> shards) {
+    return shards;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ShardAccessStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ShardAccessStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/ShardAccessStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+
+import java.util.List;
+
+public interface ShardAccessStrategy {
+  <T> T apply(List<Shard> shards, ShardOperation<T> operation, ExitStrategy<T> exitStrategy, ExitOperationsCollector exitOperationsCollector);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/StartAwareFutureTask.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/StartAwareFutureTask.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/access/StartAwareFutureTask.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.Callable;
+
+/**
+ * Extension of FutureTask that provides slightly different cancel()
+ * behavior.  We want cancel() to only return true if the task has not yet run.
+ *
+ * Multi-threaded scenario 1:
+ * run() invoked in T1
+ * The task hasn't been cancelled, so runCalled is set
+ * to true.  This happens in a synchronized block so cancel() cannot
+ * execute while the flag is being set.  Once we enter the synchronized
+ * block and get past the cancelled check we are guaranteed to run, and
+ * if cancel() is invoked at any point afterwards runCalled will be true, so
+ * cancel() will be unable to return anything other than false, which is what
+ * we want.
+ *
+ * Multi-threaded scenario 2:
+ * cancel() invoked in T1
+ * The method is synchronized, so even if T2 invokes run() it won't be able to
+ * enter the synchronized block until cancel() finishes executing.
+ * The cancelled flag is set to true, so we return right away.
+ * cancel() returns the result of super.cancel() because runCalled is guaranteed to be false.
+ *
+ * @author maxr at google.com (Max Ross)
+ * @author jbsteadman at google.com (JB Steadman)
+ */
+class StartAwareFutureTask extends FutureTask<Void> {
+
+  boolean runCalled;
+
+  boolean cancelled;
+
+  private final int id;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public StartAwareFutureTask(Callable<Void> callable, int id) {
+    super(callable);
+    this.id = id;
+  }
+
+  @Override
+  public void run() {
+
+    log.debug(String.format("Task %d: Run invoked.", id));
+    synchronized(this) {
+      if (cancelled) {
+        log.debug(String.format("Task %d: Task will not run.", id));
+        return;
+      }
+      runCalled = true;
+    }
+    log.debug(String.format("Task %d: Task will run.", id));
+    super.run();
+  }
+
+  @Override
+  public synchronized  boolean cancel(boolean mayInterruptIfRunning) {
+    if(runCalled) {
+      /**
+       * If run has already been called we can't call super.  That's because
+       * super.cancel might be called in between the time we leave the
+       * synchronization block in run() and the time we call super.run().
+       * super.run() checks the state of the FutureTask before actuall invoking
+       * the inner task, and if that check sees that this task is cancelled it
+       * won't run.  That leaves us in a position where a task actually has
+       * been cancelled but cancel returns true, so we're left with a counter
+       * that never gets decremented and everything hangs.
+       */
+      return false;
+    }
+    boolean result = superCancel(mayInterruptIfRunning);
+    cancelled = true;
+    log.debug(String.format("Task %d: Task cancelled.", id));
+    return result;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  boolean superCancel(boolean mayInterruptIfRunning) {
+    return super.cancel(mayInterruptIfRunning);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,112 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Preconditions;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.criterion.AggregateProjection;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class AggregateExitOperation implements ProjectionExitOperation {
+
+  private final SupportedAggregations aggregate;
+
+  private final SessionFactoryImplementor sessionFactoryImplementor;
+  private final String fieldName;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  private enum SupportedAggregations {
+
+    SUM("sum"),
+    MIN("min"),
+    MAX("max");
+
+    private final String aggregate;
+
+    private SupportedAggregations(String s) {
+      this.aggregate = s;
+    }
+
+    public String getAggregate() {
+      return aggregate;
+    }
+
+  }
+
+  public AggregateExitOperation(AggregateProjection projection, SessionFactoryImplementor sessionFactoryImplementor) {
+    Preconditions.checkNotNull(sessionFactoryImplementor);
+    this.sessionFactoryImplementor = sessionFactoryImplementor;
+    /**
+     * an aggregateProjection's toString returns
+     * min( ..., max( ..., sum( ..., or avg( ...
+     * we just care about the name of the function
+     * which happens to be before the first left parenthesis
+     */
+    String projectionAsString = projection.toString();
+    String aggregateName = projectionAsString.substring(0,projectionAsString.indexOf("("));
+    this.fieldName = projectionAsString.substring(projectionAsString.indexOf("(")+1, projectionAsString.indexOf(")"));
+    try {
+      this.aggregate = SupportedAggregations.valueOf(aggregateName.toUpperCase());
+    } catch (IllegalArgumentException e) {
+      log.error("Use of unsupported aggregate: "+ aggregateName);
+      throw e;
+    }
+  }
+
+  public List<Object> apply(List<Object> results) {
+
+    List<Object> nonNullResults = ExitOperationUtils.getNonNullList(results);
+
+    switch(aggregate) {
+      case MAX:
+        return Collections.singletonList((Object) Collections.max(ExitOperationUtils.getComparableList(nonNullResults)));
+      case MIN:
+        return Collections.singletonList((Object) Collections.min(ExitOperationUtils.getComparableList(nonNullResults)));
+      case SUM:
+        return Collections.<Object>singletonList(getSum(nonNullResults, fieldName));
+      default:
+        log.error("Aggregation Projection is unsupported: "+aggregate);
+        throw new UnsupportedOperationException("Aggregation Projection is unsupported: "+ aggregate);
+    }
+  }
+
+  private BigDecimal getSum(List<Object> results, String fieldName) {
+    BigDecimal sum = new BigDecimal(0.0);
+    for (Object obj : results) {
+      Number num = getNumber(obj, fieldName);
+      sum = sum.add(new BigDecimal(num.toString()));
+    }
+    return sum;
+  }
+
+  private Number getNumber(Object obj, String fieldName) {
+    return (Number) ExitOperationUtils.getPropertyValue(obj, fieldName);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ConcatenateListsExitStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ConcatenateListsExitStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ConcatenateListsExitStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+
+/**
+ * Threadsafe ExistStrategy that concatenates all the lists that are added.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class ConcatenateListsExitStrategy implements ExitStrategy<List<Object>> {
+
+  private final List<Object> result = Lists.newArrayList();
+
+  public synchronized boolean addResult(List<Object> oneResult, Shard shard) {
+    result.addAll(oneResult);
+    return false;
+  }
+
+  public List<Object> compileResults(ExitOperationsCollector exitOperationsCollector) {
+    return exitOperationsCollector.apply(result);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/CountExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/CountExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/CountExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Preconditions;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.criterion.CountProjection;
+import org.hibernate.criterion.Projection;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class CountExitOperation implements ProjectionExitOperation {
+
+  private final boolean distinct;
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public CountExitOperation(Projection projection) {
+    Preconditions.checkState(projection instanceof CountProjection);
+
+    distinct = projection.toString().indexOf("distinct") != -1;
+
+    /**
+     * TODO(maulik) we need to figure out how to work with distinct
+     * the CountProjection will return a count that is distinct for a particular
+     * shard, however, without knowing which elements it has seen, we cannot
+     * aggregate the counts.
+     */
+    log.error("not ready to use!");
+    throw new UnsupportedOperationException();
+  }
+
+  public List<Object> apply(List<Object> results) {
+    // TODO(maulik) implement this
+    log.error("not ready to use!");
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/DistinctExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/DistinctExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/DistinctExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Sets;
+
+import org.hibernate.criterion.Projection;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class DistinctExitOperation implements ExitOperation {
+
+  private final Projection distinct;
+
+  public DistinctExitOperation(Projection distinct) {
+    this.distinct = distinct;
+    //TODO (maulik) Make Distinct Work
+    throw new UnsupportedOperationException();
+  }
+
+  public List<Object> apply(List<Object> results) {
+    Set<Object> uniqueSet = Sets.newHashSet();
+    uniqueSet.addAll(ExitOperationUtils.getNonNullList(results));
+
+    List<Object> uniqueList = Lists.newArrayList(uniqueSet);
+    
+    return uniqueList;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,30 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public interface ExitOperation {
+
+  List<Object> apply(List<Object> results);
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.StringUtil;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ExitOperationUtils {
+
+  public static List<Object> getNonNullList(List<Object> list) {
+    List<Object> nonNullList = Lists.newArrayList();
+    for(Object obj : list) {
+      if(obj != null) {
+        nonNullList.add(obj);
+      }
+    }
+    return nonNullList;
+  }
+
+  public static List<Comparable> getComparableList(List<Object> results) {
+    return (List<Comparable>) (List) results;  // I feel dirty
+  }
+
+
+  public static Comparable getPropertyValue(Object obj, String propertyName) {
+    /**
+     * TODO(maulik) respect the client's choice in how Hibernate accesses
+     * property values.
+     *
+     * Currently this method access members of an object using getters only,
+     * event of the client has specifed to use direct field access. Ideally,
+     * we could get an EntityPersister from the SessionFactoryImplementor and
+     * use that. However, hibernate's EntityPersister expects all properties
+     * to be a ComponentType. In pratice, these objects are interconnected in
+     * the mapping and Hibernate instantiates them as BagType or ManyToOneType,
+     * i.e. as they are specified in the mappings. Hence, we cannot use
+     * Hibernate's EntityPersister.
+     */
+
+    try {
+      StringBuilder propertyPath = new StringBuilder();
+      for(int i=0; i < propertyName.length(); i++) {
+        String s =propertyName.substring(i,i+1);
+        if (i == 0 || propertyName.charAt(i-1) == '.') {
+          propertyPath.append(StringUtil.capitalize(s));
+        } else {
+          propertyPath.append(s);
+        }
+      }
+      String[] methods = ("get" + propertyPath.toString().replaceAll("\\.", ".get")).split("\\.");
+      Object root = obj;
+      for (int i=0; i < methods.length; i++) {
+        Class clazz = root.getClass();
+        Method m = clazz.getMethod(methods[i]);
+        root = m.invoke(root);
+        if (root == null) {
+          break;
+        }
+      }
+      return (Comparable) root;
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException(e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(e);
+    } catch (InvocationTargetException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationsCollector.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationsCollector.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitOperationsCollector.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.util.List;
+
+/**
+ * Classes that implement this interface are designed to manage the results
+ * of a incomplete execution of a query/critieria. For example, with averages
+ * the result of each query/critieria should be a list objects on which to
+ * calculate the average, rather than the avgerages on each shard. Or the
+ * the sum of maxResults(200) should be the sum of only 200 results, not the
+ * sum of the sums of 200 results per shard.
+ *
+ * @author maulik at google.com (Maulik Shah)
+ */
+public interface ExitOperationsCollector {
+
+  List<Object> apply(List<Object> result);
+
+  void setSessionFactory(SessionFactoryImplementor sessionFactoryImplementor);
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ExitStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.Shard;
+
+/**
+ * Classes implementing this interface gather results from operations that are
+ * executed across shards.  If you intend to use a specific implementation
+ * in conjunction with ParallelShardAccessStrategy that implementation must
+ * be threadsafe.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ExitStrategy<T> {
+
+  /**
+   * Add the provided result and return whether or not the caller can halt
+   * processing.
+   * @param result The result to add
+   * @return Whether or not the caller can halt processing
+   */
+  boolean addResult(T result, Shard shard);
+
+  T compileResults(ExitOperationsCollector exitOperationsCollector);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstNonNullResultExitStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstNonNullResultExitStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstNonNullResultExitStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.Shard;
+
+/**
+ * Threadsafe ExitStrategy implementation that only accepts the first result
+ * added.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class FirstNonNullResultExitStrategy<T> implements ExitStrategy<T> {
+
+  private T nonNullResult;
+  private Shard shard;
+
+  /**
+   * Synchronized method guarantees that only the first thread to add a result
+   * will have its result reflected.
+   */
+  public final synchronized boolean addResult(T result, Shard shard) {
+    if(result != null && nonNullResult == null) {
+      nonNullResult = result;
+      this.shard = shard;
+      return true;
+    }
+    return false;
+  }
+
+  public T compileResults(ExitOperationsCollector exitOperationsCollector) {
+    return nonNullResult;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstResultExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstResultExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/FirstResultExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import java.util.List;
+import java.util.Collections;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class FirstResultExitOperation implements ExitOperation {
+
+  private final int firstResult;
+
+  public FirstResultExitOperation(int firstResult) {
+    this.firstResult = firstResult;
+  }
+
+  public List<Object> apply(List<Object> results) {
+    List<Object> nonNullResults = ExitOperationUtils.getNonNullList(results);
+    if(nonNullResults.size() <= firstResult) {
+      return Collections.emptyList();
+    }
+    return nonNullResults.subList(firstResult, nonNullResults.size());
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/MaxResultsExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/MaxResultsExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/MaxResultsExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class MaxResultsExitOperation implements ExitOperation {
+
+  private final int maxResults;
+
+  public MaxResultsExitOperation(int maxResults) {
+    this.maxResults = maxResults;
+  }
+
+  public List<Object> apply(List<Object> results) {
+    List<Object> nonNullResults = ExitOperationUtils.getNonNullList(results);
+    return nonNullResults.subList(0, Math.min(nonNullResults.size(), maxResults));
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Preconditions;
+
+import org.hibernate.criterion.Order;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class OrderExitOperation implements ExitOperation {
+
+  private final Order order;
+  private final SessionFactoryImplementor sessionFactoryImplementor;
+  private final String propertyName;
+
+  public OrderExitOperation(Order order, SessionFactoryImplementor sessionFactoryImplementor) {
+    //TODO(maulik) support Ignore case!
+    Preconditions.checkState(order.toString().endsWith("asc") ||
+                             order.toString().endsWith("desc"));
+
+    this.order = order;
+    this.propertyName = getSortingProperty(order);
+    this.sessionFactoryImplementor = sessionFactoryImplementor;
+  }
+
+  public List<Object> apply(List<Object> results) {
+    List nonNullList = ExitOperationUtils.getNonNullList(results);
+    Comparator comparator = new Comparator() {
+      public int compare(Object o1, Object o2) {
+        if (o1 == o2) {
+          return 0;
+        }
+        Comparable o1Value = ExitOperationUtils.getPropertyValue(o1, propertyName);
+        Comparable o2Value = ExitOperationUtils.getPropertyValue(o2, propertyName);
+        if (o1Value == null) {
+          return -1;
+        }
+        return o1Value.compareTo(o2Value);
+      }
+    };
+
+    Collections.sort(nonNullList, comparator);
+    if (order.toString().endsWith("desc")) {
+      Collections.reverse(nonNullList);
+    }
+
+    return nonNullList;
+  }
+
+  private static String getSortingProperty(Order order) {
+    /**
+     * This method relies on the format that Order is using:
+     * propertyName + ' ' + (ascending?"asc":"desc")
+     */
+    String str = order.toString();
+    return str.substring(0, str.indexOf(' '));
+  }
+
+  
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,28 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public interface ProjectionExitOperation extends ExitOperation{
+  List<Object> apply(List<Object> results);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.criterion.AggregateProjection;
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.RowCountProjection;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ProjectionExitOperationFactory {
+
+  private final static ProjectionExitOperationFactory projectionExitOperationFactory
+      = new ProjectionExitOperationFactory();
+
+  private ProjectionExitOperationFactory() {}
+
+  public static ProjectionExitOperationFactory getFactory() {
+    return projectionExitOperationFactory;
+  }
+
+  public ProjectionExitOperation getProjectionExitOperation(Projection projection, SessionFactoryImplementor sessionFactoryImplementor) {
+    if (projection instanceof RowCountProjection) {
+      return new RowCountExitOperation(projection);
+    }
+    if (projection instanceof AggregateProjection) {
+      return new AggregateExitOperation((AggregateProjection) projection, sessionFactoryImplementor);
+    }
+
+
+    // TODO(maulik) support these projections, hopefully not by creating ShardedProjections
+    // Projection rowCount() {
+    // AggregateProjection avg(String propertyName) {
+    // CountProjection count(String propertyName) {
+    // Projection distinct(Projection proj) {
+    // ProjectionList projectionList() {
+    // CountProjection countDistinct(String propertyName) {
+    // Projection sqlProjection(String sql, String[] columnAliases, Type[] types) {
+    // Projection sqlGroupProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
+    // PropertyProjection groupProperty(String propertyName) {
+    // PropertyProjection property(String propertyName) {
+    // IdentifierProjection id() {
+    // Projection alias(Projection projection, String alias) {
+
+    throw new UnsupportedOperationException(
+        "This projection is unsupported: " + projection.getClass());
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/RowCountExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/RowCountExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/RowCountExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Preconditions;
+
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.RowCountProjection;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class RowCountExitOperation implements ProjectionExitOperation {
+
+  public RowCountExitOperation(Projection projection) {
+    Preconditions.checkState(projection instanceof RowCountProjection);
+  }
+
+  public List<Object> apply(List<Object> results) {
+    List<Object> nonNullResults = ExitOperationUtils.getNonNullList(results);
+    
+    return Collections.singletonList((Object) nonNullResults.size());
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Pair;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.criterion.Projection;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ShardedAvgExitOperation implements ProjectionExitOperation {
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  public ShardedAvgExitOperation(Projection projection) {
+    log.error("not ready to use!");
+    throw new UnsupportedOperationException();
+  }
+
+  public List<Object> apply(List<Object> results) {
+    BigDecimal value = new BigDecimal(0.0);
+    BigDecimal count = new BigDecimal(0.0);
+    for(Object obj : results) {
+      Pair<Number, Number> pair = (Pair<Number, Number>) obj;
+      // we know the order of the pair (avg, count) by convention of ShardedAvgProjection
+      value = value.add(new BigDecimal(pair.first.toString()));
+      count = count.add(new BigDecimal(pair.second.toString()));
+    }
+    return Lists.newArrayList((Object)value.divide(count));
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/AllShardsShardResolutionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/AllShardsShardResolutionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/AllShardsShardResolutionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.resolution;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class AllShardsShardResolutionStrategy extends BaseShardResolutionStrategy {
+
+  public AllShardsShardResolutionStrategy(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+
+  public List<ShardId> selectShardIdsFromShardResolutionStrategyData(
+      ShardResolutionStrategyData shardResolutionStrategyData) {
+    return shardIds;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/BaseShardResolutionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/BaseShardResolutionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/BaseShardResolutionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.resolution;
+
+import org.hibernate.shards.BaseHasShardIdList;
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseShardResolutionStrategy extends BaseHasShardIdList implements ShardResolutionStrategy {
+
+  public BaseShardResolutionStrategy(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/ShardResolutionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/ShardResolutionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/resolution/ShardResolutionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.resolution;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardResolutionStrategy {
+  /**
+   * Determine the shards on which an object might live
+   *
+   * @param shardResolutionStrategyData information we can use to select shards
+   * @return the ids of the shards on which the object described by the ShardSelectionStrategyData might reside
+   */
+  List<ShardId> selectShardIdsFromShardResolutionStrategyData(
+      ShardResolutionStrategyData shardResolutionStrategyData);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/BaseShardSelectionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/BaseShardSelectionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/BaseShardSelectionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.BaseHasShardIdList;
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseShardSelectionStrategy extends BaseHasShardIdList implements ShardSelectionStrategy {
+
+  protected BaseShardSelectionStrategy(List<ShardId> shardIds) {
+    super(shardIds);
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.loadbalance.ShardLoadBalancer;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class LoadBalancedShardSelectionStrategy implements ShardSelectionStrategy {
+
+  private final ShardLoadBalancer shardLoadBalancer;
+
+  public LoadBalancedShardSelectionStrategy(ShardLoadBalancer shardLoadBalancer) {
+    this.shardLoadBalancer = shardLoadBalancer;
+  }
+
+  public ShardId selectShardIdForNewObject(Object obj) {
+    return shardLoadBalancer.getNextShardId();
+  }
+
+  ShardLoadBalancer getShardLoadBalancer() {
+    return shardLoadBalancer;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/RoundRobinShardSelectionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/RoundRobinShardSelectionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/RoundRobinShardSelectionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.loadbalance.RoundRobinShardLoadBalancer;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class RoundRobinShardSelectionStrategy implements ShardSelectionStrategy {
+
+  private final RoundRobinShardLoadBalancer loadBalancer;
+
+  public RoundRobinShardSelectionStrategy(RoundRobinShardLoadBalancer loadBalancer) {
+    this.loadBalancer = loadBalancer;
+  }
+
+  public ShardId selectShardIdForNewObject(Object obj) {
+    return loadBalancer.getNextShardId();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyData.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyData.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyData.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardResolutionStrategyData {
+
+  String getEntityName();
+
+  Serializable getId();
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyDataImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyDataImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardResolutionStrategyDataImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardResolutionStrategyDataImpl implements ShardResolutionStrategyData {
+  private final String entityName;
+  private final Serializable id;
+
+  public ShardResolutionStrategyDataImpl(Class<?> clazz, Serializable id) {
+    this(clazz.getName(), id);
+  }
+
+  public ShardResolutionStrategyDataImpl(String entityName, Serializable id) {
+    this.entityName = entityName;
+    this.id = id;
+  }
+
+  public String getEntityName() {
+    return entityName;
+  }
+
+  public Serializable getId() {
+    return id;
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardSelectionStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardSelectionStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/strategy/selection/ShardSelectionStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.ShardId;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface ShardSelectionStrategy {
+
+  /**
+   * Determine the specific shard on which this object should reside
+   *
+   * @param obj the new object for which we are selecting a shard
+   * @return the id of the shard on which this object should live
+   */
+  ShardId selectShardIdForNewObject(Object obj);
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/transaction/ShardedTransactionImpl.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/transaction/ShardedTransactionImpl.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/transaction/ShardedTransactionImpl.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.transaction;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardedTransaction;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.engine.ShardedSessionImplementor;
+import org.hibernate.shards.session.OpenSessionEvent;
+import org.hibernate.shards.session.SetupTransactionOpenSessionEvent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.TransactionException;
+
+import java.util.List;
+import java.util.Collections;
+import java.util.ArrayList;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedTransactionImpl implements ShardedTransaction {
+
+  private final Log log = LogFactory.getLog(getClass());
+
+  private final List<Transaction> transactions;
+  private final OpenSessionEvent osEvent;
+
+  private boolean begun;
+  private boolean rolledBack;
+  private boolean committed;
+  private boolean commitFailed;
+  private List<Synchronization> synchronizations;
+  private boolean timeoutSet;
+  private int timeout;
+
+
+  public ShardedTransactionImpl(ShardedSessionImplementor ssi) {
+    osEvent = new SetupTransactionOpenSessionEvent(this);
+    transactions = Collections.synchronizedList(new ArrayList<Transaction>());
+    for(Shard shard : ssi.getShards()) {
+      if (shard.getSession() != null) {
+        transactions.add(shard.getSession().getTransaction());
+      } else {
+        shard.addOpenSessionEvent(osEvent);
+      }
+    }
+  }
+
+  public void setupTransaction(Session session) {
+    log.debug("Setting up transaction");
+    transactions.add(session.getTransaction());
+    if (begun) {
+     session.beginTransaction();
+    }
+    if (timeoutSet) {
+      session.getTransaction().setTimeout(timeout);
+    }
+  }
+
+  public void begin() throws HibernateException {
+    if (begun) {
+      return;
+    }
+    if (commitFailed) {
+      throw new TransactionException("cannot re-start transaction after failed commit");
+    }
+    boolean beginException = false;
+    for (Transaction t : transactions) {
+      try {
+        t.begin();
+      } catch (HibernateException he) {
+        log.warn("exception starting underlying transaction", he);
+        beginException = true;
+      }
+    }
+    if (beginException) {
+      for (Transaction t : transactions) {
+        if (t.isActive()) {
+          try {
+            t.rollback();
+          } catch (HibernateException he) {
+            // TODO(maxr) What do we do?
+          }
+
+        }
+      }
+      throw new TransactionException("Begin failed");
+    }
+    begun = true;
+    committed = false;
+    rolledBack = false;
+  }
+
+  public void commit() throws HibernateException {
+    if (!begun) {
+      throw new TransactionException("Transaction not succesfully started");
+    }
+    log.debug("Starting transaction commit");
+    beforeTransactionCompletion();
+    boolean commitException = false;
+    for(Transaction t : transactions) {
+      try {
+        t.commit();
+      } catch (HibernateException he) {
+        log.warn("exception commiting underlying transaction", he);
+        commitException = true;
+      }
+    }
+    if (commitException) {
+      commitFailed  = true;
+      afterTransactionCompletion(Status.STATUS_UNKNOWN);
+      throw new TransactionException("Commit failed");
+    }
+    afterTransactionCompletion(Status.STATUS_COMMITTED);
+    committed = true;
+  }
+
+  public void rollback() throws HibernateException {
+    if (!begun && !commitFailed) {
+      throw new TransactionException("Transaction not successfully started");
+    }
+    boolean rollbackException = false;
+    for(Transaction t : transactions) {
+      if (t.wasCommitted()) {
+        continue;
+      }
+      try {
+        t.rollback();
+      } catch (HibernateException he) {
+        log.warn("exception rolling back underlying transaction", he);
+        rollbackException = true;
+      }
+    }
+    if (rollbackException) {
+      throw new TransactionException("Rollback failed");
+    }
+    rolledBack = true;
+  }
+
+  public boolean wasRolledBack() throws HibernateException {
+    return rolledBack;
+  }
+
+  public boolean wasCommitted() throws HibernateException {
+    return committed;
+  }
+
+  public boolean isActive() throws HibernateException {
+    return begun && !(rolledBack || committed || commitFailed);
+  }
+
+  public void registerSynchronization(Synchronization sync)
+      throws HibernateException {
+    if (sync == null) {
+      throw new NullPointerException("null Synchronization");
+    }
+    if (synchronizations == null) {
+      synchronizations = Lists.newArrayList();
+    }
+    synchronizations.add(sync);
+  }
+
+  public void setTimeout(int seconds) {
+    timeoutSet = true;
+    timeout = seconds;
+    for(Transaction t : transactions) {
+      t.setTimeout(timeout);
+    }
+  }
+
+  private void beforeTransactionCompletion() {
+    if (synchronizations != null) {
+      for (Synchronization sync : synchronizations) {
+        try {
+          sync.beforeCompletion();
+        } catch (Throwable t) {
+          log.warn("exception calling user Synchronization", t);
+        }
+      }
+    }
+  }
+
+  private void afterTransactionCompletion(int status) {
+    begun = false;
+    if (synchronizations != null) {
+      for (Synchronization sync : synchronizations) {
+        try {
+          sync.afterCompletion(status);
+        } catch (Throwable t) {
+          log.warn("exception calling user Synchronization", t);
+        }
+      }
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/InterceptorDecorator.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/InterceptorDecorator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/InterceptorDecorator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,132 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import org.hibernate.Interceptor;
+import org.hibernate.CallbackException;
+import org.hibernate.EntityMode;
+import org.hibernate.Transaction;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+/**
+ * {@link Interceptor} implementation that delegates all calls to an inner
+ * {@link Interceptor}.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class InterceptorDecorator implements Interceptor {
+
+  protected final Interceptor delegate;
+
+  public InterceptorDecorator(Interceptor delegate) {
+    this.delegate = delegate;
+  }
+
+  public boolean onLoad(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    return delegate.onLoad(entity, id, state, propertyNames, types);
+  }
+
+  public boolean onFlushDirty(Object entity, Serializable id,
+      Object[] currentState, Object[] previousState, String[] propertyNames,
+      Type[] types) throws CallbackException {
+    return delegate.onFlushDirty(entity, id, currentState, previousState,
+        propertyNames, types);
+  }
+
+  public boolean onSave(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    return delegate.onSave(entity, id, state, propertyNames, types);
+  }
+
+  public void onDelete(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    delegate.onDelete(entity, id, state, propertyNames, types);
+  }
+
+  public void onCollectionRecreate(Object collection, Serializable key) throws
+      CallbackException {
+    delegate.onCollectionRecreate(collection, key);
+  }
+
+  public void onCollectionRemove(Object collection, Serializable key) throws
+      CallbackException {
+    delegate.onCollectionRemove(collection, key);
+  }
+
+  public void onCollectionUpdate(Object collection, Serializable key) throws
+      CallbackException {
+    delegate.onCollectionUpdate(collection, key);
+  }
+
+  public void preFlush(Iterator entities) throws CallbackException {
+    delegate.preFlush(entities);
+  }
+
+  public void postFlush(Iterator entities) throws CallbackException {
+    delegate.postFlush(entities);
+  }
+
+  public Boolean isTransient(Object entity) {
+    return delegate.isTransient(entity);
+  }
+
+  public int[] findDirty(Object entity, Serializable id, Object[] currentState,
+      Object[] previousState, String[] propertyNames, Type[] types) {
+    return delegate
+        .findDirty(entity, id, currentState, previousState, propertyNames, types);
+  }
+
+  public Object instantiate(String entityName, EntityMode entityMode,
+      Serializable id) throws CallbackException {
+    return delegate.instantiate(entityName, entityMode, id);
+  }
+
+  public String getEntityName(Object object) throws CallbackException {
+    return delegate.getEntityName(object);
+  }
+
+  public Object getEntity(String entityName, Serializable id) throws
+      CallbackException {
+    return delegate.getEntity(entityName, id);
+  }
+
+  public void afterTransactionBegin(Transaction tx) {
+    delegate.afterTransactionBegin(tx);
+  }
+
+  public void beforeTransactionCompletion(Transaction tx) {
+    delegate.beforeTransactionCompletion(tx);
+  }
+
+  public void afterTransactionCompletion(Transaction tx) {
+    delegate.afterTransactionCompletion(tx);
+  }
+
+  public String onPrepareStatement(String sql) {
+    return delegate.onPrepareStatement(sql);
+  }
+
+  public Interceptor getDelegate() {
+    return delegate;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Iterables.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Iterables.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Iterables.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collections;
+
+/**
+ * Helper methods related to {@link Iterable}s.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class Iterables {
+
+  private Iterables() {}
+
+  /**
+   * @return an Iterable that allows you to iterate over the contents of
+   * all the iterables passed in.
+   */
+  public static <T> Iterable<T> concat(Iterable<? extends T>... iterables) {
+    List<T> list = Lists.newArrayList();
+    for(Iterable<? extends T> subIterable : iterables) {
+      for(T obj : subIterable) {
+        list.add(obj);
+      }
+    }
+    return list;
+  }
+
+  /**
+   * @return an Iterable that allows you to iterate over the contents of
+   * all the iterables passed in.
+   */
+  public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> iterable) {
+    List<T> list = Lists.newArrayList();
+    for(Iterable<? extends T> subIterable : iterable) {
+      for(T obj : subIterable) {
+        list.add(obj);
+      }
+    }
+    return list;
+  }
+
+  /**
+   * Provides a rotated view of a list.  Differs from {@link Collections#rotate}
+   * only in that it leaves the underlying list unchanged.  Note that this is a
+   * "live" view of the list that will change as the list changes.  However, the
+   * behavior of an {@link Iterator} constructed from a rotated view of the list
+   * is undefined if the list is changed after the Iterator is constructed.
+   *
+   * @param list the list to return a rotated view of.
+   * @param distance the distance to rotate the list.  There are no constraints
+   * on this value; it may be zero, negative, or greater than
+   * {@code list.size()}.
+   * @return a rotated view of the given list
+   */
+  public static <T> Iterable<T> rotate(final List<T> list, final int distance) {
+    Preconditions.checkNotNull(list);
+
+    /*
+     * If no rotation is requested or there is nothing to rotate (list of size
+     * 0 or 1), just return the original list
+     */
+    if (distance == 0 || list.size() <= 1) {
+      return list;
+    }
+
+    return new Iterable<T>() {
+      /**
+       * Determines the actual distance we need to rotate (distance provided
+       * might be larger than the size of the list or negative).
+       */
+      private int calcActualDistance(int size) {
+        // we already know distance and size are non-zero
+        int actualDistance = distance % size;
+        if (actualDistance < 0) {
+          // distance must have been negative
+          actualDistance += size;
+        }
+        return actualDistance;
+      }
+
+      public Iterator<T> iterator() {
+        int size = list.size();
+        int actualDistance = calcActualDistance(size);
+        // optimization:
+        // lists of a size that go into the distance evenly don't need rotation
+        if (actualDistance == 0) {
+          return list.iterator();
+        }
+
+        @SuppressWarnings("unchecked")
+        Iterable<T> rotated = concat(
+            list.subList(actualDistance, size), list.subList(0, actualDistance));
+        return rotated.iterator();
+      }
+    };
+  }
+
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Lists.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Lists.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Lists.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,80 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Helper methods related to {@link List}s.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class Lists {
+
+  private Lists() { }
+
+  /**
+   * Construct a new {@link ArrayList}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> ArrayList<E> newArrayList() {
+    return new ArrayList<E>();
+  }
+
+  /**
+   * Construct a new {@link ArrayList} with the specified capacity, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> ArrayList<E> newArrayListWithCapacity(int initialCapacity) {
+    return new ArrayList<E>(initialCapacity);
+  }
+
+  /**
+   * Construct a new {@link ArrayList} with the provided elements, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> ArrayList<E> newArrayList(E... elements) {
+    ArrayList<E> set = newArrayList();
+    Collections.addAll(set, elements);
+    return set;
+  }
+
+  /**
+   * Construct a new {@link ArrayList} with the contents of the provided {@link Iterable}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
+    ArrayList<E> list = newArrayList();
+    for(E e : elements) {
+      list.add(e);
+    }
+    return list;
+  }
+
+  /**
+   * Construct a new {@link LinkedList}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> LinkedList<E> newLinkedList() {
+    return new LinkedList<E>();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Maps.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Maps.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Maps.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Helper methods related to {@link Map}s.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class Maps {
+
+  private Maps() {}
+
+  /**
+   * Construct a new {@link HashMap}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <K, V> HashMap<K, V> newHashMap() {
+    return new HashMap<K, V>();
+  }
+
+  /**
+   * Construct a new {@link LinkedHashMap}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap() {
+    return new LinkedHashMap<K, V>();
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Pair.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Pair.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Pair.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+/**
+ * A simple class to represent a pair.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class Pair<A,B> {
+  public final A first;
+
+  /** The second element of the pair. */
+  public final B second;
+
+  private Pair(/*@Nullable*/ A first, /*@Nullable*/ B second) {
+    this.first = first;
+    this.second = second;
+  }
+
+  public A getFirst() {
+    return first;
+  }
+
+  public B getSecond() {
+    return second;
+  }
+
+  public static <A,B> Pair<A,B> of(/*@Nullable*/ A first, /*@Nullable*/ B second) {
+    return new Pair<A,B>(first, second);
+  }
+
+  private static boolean eq(/*@Nullable*/ Object a, /*@Nullable*/ Object b) {
+    return a == b || (a != null && a.equals(b));
+  }
+
+  @Override
+  public boolean equals(/*@Nullable*/ Object object) {
+    if (object instanceof Pair<?,?>) {
+      Pair<?,?> other = (Pair<?,?>) object;
+      return eq(first, other.first) && eq(second, other.second);
+    }
+    return false;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Preconditions.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Preconditions.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Preconditions.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+/**
+ * Helper methods for checking preconditions.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class Preconditions {
+
+  private Preconditions() { }
+
+  /**
+   * @param expression the boolean to evaluate
+   * @throws IllegalArgumentException thrown if boolean is false
+   */
+  public static void checkArgument(boolean expression) {
+    if (!expression) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * @param expression the boolean to evaluate
+   * @throws IllegalStateException thrown if boolean is false
+   */
+  public static void checkState(boolean expression) {
+    if (!expression) {
+      throw new IllegalStateException();
+    }
+  }
+
+  /**
+   * @param reference the object to compare against null
+   * @throws NullPointerException thrown if object is null
+   */
+  public static void checkNotNull(Object reference) {
+    if (reference == null) {
+      throw new NullPointerException();
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Sets.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Sets.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/Sets.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper methods related to {@link Set}s.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class Sets {
+  private Sets() {}
+
+  /**
+   * Construct a new {@link HashSet}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> HashSet<E> newHashSet() {
+    return new HashSet<E>();
+  }
+
+  /**
+   * Construct a new {@link HashSet} with the provided elements, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> HashSet<E> newHashSet(E... elements) {
+    HashSet<E> set = newHashSet();
+    Collections.addAll(set, elements);
+    return set;
+  }
+
+  /**
+   * Construct a new {@link HashSet} with the contents of the provided {@link Iterable}, taking advantage of type inference to
+   * avoid specifying the type on the rhs.
+   */
+  public static <E> HashSet<E> newHashSet(Iterable<? extends E> elements) {
+    HashSet<E> set = newHashSet();
+    for(E e : elements) {
+      set.add(e);
+    }
+    return set;
+  }
+}

Added: trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/StringUtil.java
===================================================================
--- trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/StringUtil.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/java/org/hibernate/shards/util/StringUtil.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,73 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+/**
+ * String utilities.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class StringUtil {
+
+  /**
+   * Helper function for null, empty, and whitespace string testing.
+   *
+   * @return true if s == null or s.equals("") or s contains only whitespace
+   *         characters.
+   */
+  public static boolean isEmptyOrWhitespace(String s) {
+    s = makeSafe(s);
+    for (int i = 0, n = s.length(); i < n; i++) {
+      if (!Character.isWhitespace(s.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * @return true if s == null or s.equals("")
+   */
+  public static boolean isEmpty(String s) {
+    return makeSafe(s).length() == 0;
+  }
+
+  /**
+   * Helper function for making null strings safe for comparisons, etc.
+   *
+   * @return (s == null) ? "" : s;
+   */
+  public static String makeSafe(String s) {
+    return (s == null) ? "" : s;
+  }
+
+  /**
+   * @return the string provided with its first character capitalized
+   */
+  public static String capitalize(String s) {
+    if (s.length() == 0) {
+      return s;
+    }
+    char first = s.charAt(0);
+    char capitalized = Character.toUpperCase(first);
+    return (first == capitalized)
+        ? s
+        : capitalized + s.substring(1);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllFastTests.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllFastTests.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllFastTests.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,51 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.integration.PermutedIntegrationTests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class AllFastTests extends TestSuite {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    for(Class<? extends TestCase> testClass : getAllFastTestClasses()) {
+      suite.addTestSuite(testClass);
+    }
+    return suite;
+  }
+
+  private static List<Class<? extends TestCase>> getAllFastTestClasses() {
+    List<Class<? extends TestCase>> allFastTestClasses = new ArrayList<Class<? extends TestCase>>();
+    for(Class<? extends TestCase> testClass : AllTests.CLASSES) {
+      allFastTestClasses.add(testClass);
+    }
+    allFastTestClasses.removeAll(PermutedIntegrationTests.CLASSES);
+    return allFastTestClasses;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllTests.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllTests.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/AllTests.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,214 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.shards.criteria.AddCriterionEventTest;
+import org.hibernate.shards.criteria.AddOrderEventTest;
+import org.hibernate.shards.criteria.CreateAliasEventTest;
+import org.hibernate.shards.criteria.CreateSubcriteriaEventTest;
+import org.hibernate.shards.criteria.CriteriaFactoryImplTest;
+import org.hibernate.shards.criteria.SetFetchModeEventTest;
+import org.hibernate.shards.criteria.SetProjectionEventTest;
+import org.hibernate.shards.criteria.ShardedSubcriteriaImplTest;
+import org.hibernate.shards.criteria.SubcriteriaFactoryImplTest;
+import org.hibernate.shards.id.ShardedTableHiLoGeneratorTest;
+import org.hibernate.shards.id.ShardedUUIDGeneratorTest;
+import org.hibernate.shards.integration.PermutedIntegrationTests;
+import org.hibernate.shards.integration.model.MemoryLeakTest;
+import org.hibernate.shards.loadbalance.RoundRobinShardLoadBalancerTest;
+import org.hibernate.shards.query.SetBigDecimalEventTest;
+import org.hibernate.shards.query.SetBigIntegerEventTest;
+import org.hibernate.shards.query.SetBinaryEventTest;
+import org.hibernate.shards.query.SetBooleanEventTest;
+import org.hibernate.shards.query.SetByteEventTest;
+import org.hibernate.shards.query.SetCalendarDateEventTest;
+import org.hibernate.shards.query.SetCalendarEventTest;
+import org.hibernate.shards.query.SetCharacterEventTest;
+import org.hibernate.shards.query.SetDateEventTest;
+import org.hibernate.shards.query.SetDoubleEventTest;
+import org.hibernate.shards.query.SetEntityEventTest;
+import org.hibernate.shards.query.SetFloatEventTest;
+import org.hibernate.shards.query.SetIntegerEventTest;
+import org.hibernate.shards.query.SetLocaleEventTest;
+import org.hibernate.shards.query.SetLongEventTest;
+import org.hibernate.shards.query.SetParameterEventTest;
+import org.hibernate.shards.query.SetParameterListEventTest;
+import org.hibernate.shards.query.SetParametersEventTest;
+import org.hibernate.shards.query.SetPropertiesEventTest;
+import org.hibernate.shards.query.SetReadOnlyEventTest;
+import org.hibernate.shards.query.SetSerializableEventTest;
+import org.hibernate.shards.query.SetShortEventTest;
+import org.hibernate.shards.query.SetStringEventTest;
+import org.hibernate.shards.query.SetTextEventTest;
+import org.hibernate.shards.query.SetTimeEventTest;
+import org.hibernate.shards.query.SetTimestampEventTest;
+import org.hibernate.shards.session.CrossShardRelationshipDetectingInterceptorDecoratorTest;
+import org.hibernate.shards.session.CrossShardRelationshipDetectingInterceptorTest;
+import org.hibernate.shards.session.DisableFilterOpenSessionEventTest;
+import org.hibernate.shards.session.EnableFilterOpenSessionEventTest;
+import org.hibernate.shards.session.SetCacheModeOpenSessionEventTest;
+import org.hibernate.shards.session.SetFlushModeOpenSessionEventTest;
+import org.hibernate.shards.session.SetReadOnlyOpenSessionEventTest;
+import org.hibernate.shards.session.SetSessionOnRequiresSessionEventTest;
+import org.hibernate.shards.session.ShardedSessionFactoryImplTest;
+import org.hibernate.shards.session.ShardedSessionImplTest;
+import org.hibernate.shards.strategy.access.ParallelShardAccessStrategyTest;
+import org.hibernate.shards.strategy.access.ParallelShardOperationCallableTest;
+import org.hibernate.shards.strategy.access.StartAwareFutureTaskTest;
+import org.hibernate.shards.strategy.exit.AggregateExitOperationTest;
+import org.hibernate.shards.strategy.exit.ExitOperationUtilsTest;
+import org.hibernate.shards.strategy.exit.FirstResultExitOperationTest;
+import org.hibernate.shards.strategy.exit.MaxResultExitOperationTest;
+import org.hibernate.shards.strategy.exit.OrderExitOperationTest;
+import org.hibernate.shards.strategy.exit.ProjectionExitOperationFactoryTest;
+import org.hibernate.shards.strategy.exit.RowCountExitOperationTest;
+import org.hibernate.shards.strategy.selection.LoadBalancedShardSelectionStrategyTest;
+import org.hibernate.shards.transaction.ShardedTransactionImplTest;
+import org.hibernate.shards.util.Lists;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is really just here for IDE users who want to run their tests
+ * directly instead of through Ant.  Almost guaranteed to fall out of
+ * synch.
+ * TODO(maxr) destroy
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class AllTests extends TestSuite {
+
+  public static final List<Class<? extends TestCase>> CLASSES = Collections.unmodifiableList(buildListOfClasses());
+
+  private static List<Class<? extends TestCase>> buildListOfClasses() {
+    Set<Class<? extends TestCase>> classes = new HashSet<Class<? extends TestCase>>();
+    add(classes, BaseHasShardIdListTest.class);
+    add(classes, ShardImplTest.class);
+    add(classes, SetBigDecimalEventTest.class);
+    add(classes, SetBigIntegerEventTest.class);
+    add(classes, SetBinaryEventTest.class);
+    add(classes, SetBooleanEventTest.class);
+    add(classes, SetByteEventTest.class);
+    add(classes, org.hibernate.shards.query.SetCacheModeEventTest.class);
+    add(classes, org.hibernate.shards.query.SetCacheRegionEventTest.class);
+    add(classes, org.hibernate.shards.query.SetCacheableEventTest.class);
+    add(classes, SetCalendarDateEventTest.class);
+    add(classes, SetCalendarEventTest.class);
+    add(classes, SetCharacterEventTest.class);
+    add(classes, SetSessionOnRequiresSessionEventTest.class);
+    add(classes, org.hibernate.shards.query.SetCommentEventTest.class);
+    add(classes, SetDateEventTest.class);
+    add(classes, SetDoubleEventTest.class);
+    add(classes, SetEntityEventTest.class);
+    add(classes, org.hibernate.shards.query.SetFetchSizeEventTest.class);
+    add(classes, org.hibernate.shards.query.SetFirstResultEventTest.class);
+    add(classes, SetFloatEventTest.class);
+    add(classes, org.hibernate.shards.query.SetFlushModeEventTest.class);
+    add(classes, SetIntegerEventTest.class);
+    add(classes, SetLocaleEventTest.class);
+    add(classes, org.hibernate.shards.query.SetLockModeEventTest.class);
+    add(classes, SetLongEventTest.class);
+    add(classes, org.hibernate.shards.query.SetMaxResultsEventTest.class);
+    add(classes, SetParameterEventTest.class);
+    add(classes, SetParameterListEventTest.class);
+    add(classes, SetParametersEventTest.class);
+    add(classes, SetPropertiesEventTest.class);
+    add(classes, SetReadOnlyEventTest.class);
+    add(classes, org.hibernate.shards.query.SetResultTransformerEventTest.class);
+    add(classes, SetSerializableEventTest.class);
+    add(classes, SetShortEventTest.class);
+    add(classes, SetStringEventTest.class);
+    add(classes, SetTextEventTest.class);
+    add(classes, SetTimeEventTest.class);
+    add(classes, org.hibernate.shards.query.SetTimeoutEventTest.class);
+    add(classes, SetTimestampEventTest.class);
+    add(classes, ShardedConfigurationTest.class);
+    add(classes, ShardedSessionFactoryImplTest.class);
+    add(classes, AddCriterionEventTest.class);
+    add(classes, AddOrderEventTest.class);
+    add(classes, CreateAliasEventTest.class);
+    add(classes, CriteriaFactoryImplTest.class);
+    add(classes, org.hibernate.shards.criteria.SetCacheModeEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetCacheRegionEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetCacheableEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetCommentEventTest.class);
+    add(classes, SetFetchModeEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetFetchSizeEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetFirstResultEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetFlushModeEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetLockModeEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetMaxResultsEventTest.class);
+    add(classes, SetProjectionEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetResultTransformerEventTest.class);
+    add(classes, org.hibernate.shards.criteria.SetTimeoutEventTest.class);
+    add(classes, CreateSubcriteriaEventTest.class);
+    add(classes, SubcriteriaFactoryImplTest.class);
+    add(classes, ShardedSubcriteriaImplTest.class);
+    add(classes, ShardedUUIDGeneratorTest.class);
+    add(classes, ShardedTableHiLoGeneratorTest.class);
+    add(classes, MemoryLeakTest.class);
+    add(classes, RoundRobinShardLoadBalancerTest.class);
+    add(classes, DisableFilterOpenSessionEventTest.class);
+    add(classes, EnableFilterOpenSessionEventTest.class);
+    add(classes, SetCacheModeOpenSessionEventTest.class);
+    add(classes, SetFlushModeOpenSessionEventTest.class);
+    add(classes, SetReadOnlyOpenSessionEventTest.class);
+    add(classes, ShardedSessionImplTest.class);
+    add(classes, CrossShardRelationshipDetectingInterceptorDecoratorTest.class);
+    add(classes, CrossShardRelationshipDetectingInterceptorTest.class);
+    add(classes, ParallelShardAccessStrategyTest.class);
+    add(classes, StartAwareFutureTaskTest.class);
+    add(classes, ParallelShardOperationCallableTest.class);
+    add(classes, AggregateExitOperationTest.class);
+    add(classes, FirstResultExitOperationTest.class);
+    add(classes, MaxResultExitOperationTest.class);
+    add(classes, ProjectionExitOperationFactoryTest.class);
+    add(classes, RowCountExitOperationTest.class);
+    add(classes, ExitOperationUtilsTest.class);
+    add(classes, OrderExitOperationTest.class);
+    add(classes, LoadBalancedShardSelectionStrategyTest.class);
+    add(classes, ShardedTransactionImplTest.class);
+    add(classes, InstanceShardStrategyImplTest.class);
+
+    return Lists.newArrayList(classes);
+  }
+
+  private static void add(Set<Class<? extends TestCase>> classes,
+      Class<? extends TestCase> aClass) {
+    if(!classes.add(aClass)) {
+      throw new RuntimeException("Class " + aClass.getName() + " is listed more than once.");
+    }
+  }
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    for(Class<? extends TestCase> testClass : CLASSES) {
+      suite.addTestSuite(testClass);
+    }
+    suite.addTest(PermutedIntegrationTests.suite());
+    return suite;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/BaseHasShardIdListTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/BaseHasShardIdListTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/BaseHasShardIdListTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import junit.framework.TestCase;
+
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class BaseHasShardIdListTest extends TestCase {
+
+  public void testShardIdListUnmodifiable() {
+    List<ShardId> shardIdList = null;
+    try {
+      new MyBaseHasShardIdList(shardIdList);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+    shardIdList = Lists.newArrayList();
+    try {
+      new MyBaseHasShardIdList(shardIdList);
+      fail("expected iae");
+    } catch (IllegalArgumentException iae) {
+      // good
+    }
+    shardIdList.add(new ShardId(0));
+    BaseHasShardIdList bhsil = new MyBaseHasShardIdList(shardIdList);
+    ShardId anotherId = new ShardId(1);
+    shardIdList.add(anotherId);
+    // demonstrate that external changes to the list that was passed in
+    // aren't reflected inside the object
+    assertFalse(bhsil.shardIds.contains(anotherId));
+  }
+
+  private static final class MyBaseHasShardIdList extends BaseHasShardIdList {
+
+    protected MyBaseHasShardIdList(List<ShardId> shardIds) {
+      super(shardIds);
+    }
+
+    public ShardId selectShardIdForNewObject(Object obj) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/InstanceShardStrategyImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/InstanceShardStrategyImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/InstanceShardStrategyImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.strategy.ShardStrategyImpl;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategyDefaultMock;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.access.ShardAccessStrategyDefaultMock;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategyDefaultMock;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class InstanceShardStrategyImplTest extends TestCase {
+
+  public void testCtor() {
+    try {
+      new ShardStrategyImpl(null, null, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    ShardSelectionStrategy sss = new ShardSelectionStrategyDefaultMock();
+    ShardResolutionStrategy srs = new ShardResolutionStrategyDefaultMock();
+    ShardAccessStrategy sas = new ShardAccessStrategyDefaultMock();
+    try {
+      new ShardStrategyImpl(sss, null, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    try {
+      new ShardStrategyImpl(null, srs, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    try {
+      new ShardStrategyImpl(null, null, sas);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    try {
+      new ShardStrategyImpl(sss, srs, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+
+    try {
+      new ShardStrategyImpl(null, srs, sas);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+    new ShardStrategyImpl(sss, srs, sas);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,151 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.criteria.CriteriaEvent;
+import org.hibernate.shards.criteria.CriteriaId;
+import org.hibernate.shards.criteria.ShardedCriteria;
+import org.hibernate.shards.query.QueryEvent;
+import org.hibernate.shards.query.QueryId;
+import org.hibernate.shards.query.ShardedQuery;
+import org.hibernate.shards.session.OpenSessionEvent;
+
+import org.hibernate.Criteria;
+import org.hibernate.LockMode;
+import org.hibernate.Query;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardDefaultMock implements Shard {
+
+  public SessionFactoryImplementor getSessionFactoryImplementor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session getSession() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void addOpenSessionEvent(OpenSessionEvent event) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session establishSession() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria getCriteriaById(CriteriaId id) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void addCriteriaEvent(CriteriaId id, CriteriaEvent event) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria establishCriteria(ShardedCriteria shardedCriteria) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class<?> clazz, Serializable id) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class<?> clazz, Serializable id, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<Object> list(CriteriaId criteriaId) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult(CriteriaId criteriaId) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(String entityName, Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(String entityName, Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(String entityName, Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(String entityName, Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set<ShardId> getShardIds() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getQueryById(QueryId queryId) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void addQueryEvent(QueryId id, QueryEvent event) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query establishQuery(ShardedQuery shardedQuery) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<Object> list(QueryId queryId) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult(QueryId queryId) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,530 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.session.OpenSessionEvent;
+import org.hibernate.shards.session.OpenSessionEventDefaultMock;
+import org.hibernate.shards.criteria.CriteriaId;
+import org.hibernate.shards.criteria.CriteriaEventDefaultMock;
+import org.hibernate.shards.criteria.CriteriaEvent;
+import org.hibernate.shards.criteria.CriteriaFactory;
+import org.hibernate.shards.criteria.ShardedCriteriaDefaultMock;
+import org.hibernate.shards.criteria.CriteriaFactoryDefaultMock;
+import org.hibernate.shards.query.QueryId;
+import org.hibernate.shards.query.QueryEventDefaultMock;
+import org.hibernate.shards.query.QueryEvent;
+import org.hibernate.shards.query.QueryFactory;
+import org.hibernate.shards.query.ShardedQueryDefaultMock;
+import org.hibernate.shards.query.QueryFactoryDefaultMock;
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.defaultmock.InterceptorDefaultMock;
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+import org.hibernate.shards.util.Sets;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardImplTest extends TestCase {
+
+  public void testAddOpenSessionEvent() {
+    ShardImpl shard = new ShardImpl(new ShardId(1), new SessionFactoryDefaultMock());
+    try {
+      shard.addOpenSessionEvent(null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+    OpenSessionEvent ose = new OpenSessionEventDefaultMock();
+    shard.addOpenSessionEvent(ose);
+    assertNotNull(shard.getOpenSessionEvents());
+    assertEquals(1, shard.getOpenSessionEvents().size());
+    assertSame(ose, shard.getOpenSessionEvents().get(0));
+
+    // now add another and make sure it is added to the end
+    OpenSessionEvent anotherOse = new OpenSessionEventDefaultMock();
+    shard.addOpenSessionEvent(anotherOse);
+    assertNotNull(shard.getOpenSessionEvents());
+    assertEquals(2, shard.getOpenSessionEvents().size());
+    assertSame(ose, shard.getOpenSessionEvents().get(0));
+    assertSame(anotherOse, shard.getOpenSessionEvents().get(1));
+  }
+
+  public void testAddCriteriaEvent() {
+    ShardImpl shard = new ShardImpl(new ShardId(1), new SessionFactoryDefaultMock());
+    try {
+      shard.addCriteriaEvent(null, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    CriteriaId criteriaId = new CriteriaId(2);
+    try {
+      shard.addCriteriaEvent(criteriaId, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    CriteriaEvent ce = new CriteriaEventDefaultMock();
+    try {
+      shard.addCriteriaEvent(null, ce);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    shard.addCriteriaEvent(criteriaId, ce);
+    assertNotNull(shard.getCriteriaEventMap());
+    assertEquals(1, shard.getCriteriaEventMap().size());
+    assertEquals(1, shard.getCriteriaEventMap().get(criteriaId).size());
+    assertSame(ce, shard.getCriteriaEventMap().get(criteriaId).get(0));
+
+    // now add another event to the same criteria
+    CriteriaEvent anotherCe = new CriteriaEventDefaultMock();
+    shard.addCriteriaEvent(criteriaId, anotherCe);
+    assertNotNull(shard.getCriteriaEventMap());
+    assertEquals(1, shard.getCriteriaEventMap().size());
+    assertEquals(2, shard.getCriteriaEventMap().get(criteriaId).size());
+    assertSame(ce, shard.getCriteriaEventMap().get(criteriaId).get(0));
+    assertSame(anotherCe, shard.getCriteriaEventMap().get(criteriaId).get(1));
+
+    // now add an event to a different criteria
+    CriteriaId anotherCriteriaId = new CriteriaId(3);
+    CriteriaEvent yetAnotherCe = new CriteriaEventDefaultMock();
+    shard.addCriteriaEvent(anotherCriteriaId, yetAnotherCe);
+    assertNotNull(shard.getCriteriaEventMap());
+    assertEquals(2, shard.getCriteriaEventMap().size());
+    assertEquals(2, shard.getCriteriaEventMap().get(criteriaId).size());
+    assertSame(ce, shard.getCriteriaEventMap().get(criteriaId).get(0));
+    assertSame(anotherCe, shard.getCriteriaEventMap().get(criteriaId).get(1));
+    assertEquals(1, shard.getCriteriaEventMap().get(anotherCriteriaId).size());
+    assertSame(yetAnotherCe, shard.getCriteriaEventMap().get(anotherCriteriaId).get(0));
+  }
+
+  public void testEstablishSessionNoEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionCalls);
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionCalls);
+  }
+
+  public void testEstablishSessionNoEventsWithInterceptor() {
+    MySessionFactory sf = new MySessionFactory();
+    Interceptor interceptor = new InterceptorDefaultMock();
+    ShardImpl shardImpl = new ShardImpl(Sets.newHashSet(new ShardId(1)), sf, interceptor);
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionWithInterceptorCalls);
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionWithInterceptorCalls);
+  }
+
+  public void testEstablishSessionWithEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    MyOpenSessionEvent event1 = new MyOpenSessionEvent();
+    MyOpenSessionEvent event2 = new MyOpenSessionEvent();
+    shardImpl.addOpenSessionEvent(event1);
+    shardImpl.addOpenSessionEvent(event2);
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertEquals(1, event1.numOnOpenSessionCalls);
+    assertEquals(1, event2.numOnOpenSessionCalls);
+    assertTrue(shardImpl.getOpenSessionEvents().isEmpty());
+    shardImpl.establishSession();
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertEquals(1, event1.numOnOpenSessionCalls);
+    assertEquals(1, event2.numOnOpenSessionCalls);
+    assertTrue(shardImpl.getOpenSessionEvents().isEmpty());
+  }
+
+  public void testEstablishCriteriaNoEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    CriteriaId critId = new CriteriaId(3);
+    Criteria crit = new CriteriaDefaultMock();
+    MyCriteriaFactory mcf = new MyCriteriaFactory(crit);
+    MyShardedCriteria msc = new MyShardedCriteria(critId, mcf);
+    shardImpl.establishCriteria(msc);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mcf.createCriteriaCalledWith);
+    assertEquals(1, shardImpl.getCriteriaMap().size());
+    assertSame(crit, shardImpl.getCriteriaMap().get(critId));
+
+    shardImpl.establishCriteria(msc);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mcf.createCriteriaCalledWith);
+    assertEquals(1, shardImpl.getCriteriaMap().size());
+    assertSame(crit, shardImpl.getCriteriaMap().get(critId));
+  }
+
+  public void testEstablishCriteriaWithEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    MyCriteriaEvent event1 = new MyCriteriaEvent();
+    MyCriteriaEvent event2 = new MyCriteriaEvent();
+    CriteriaId critId = new CriteriaId(3);
+    shardImpl.addCriteriaEvent(critId, event1);
+    shardImpl.addCriteriaEvent(critId, event2);
+    Criteria crit = new CriteriaDefaultMock();
+    MyCriteriaFactory mcf = new MyCriteriaFactory(crit);
+    MyShardedCriteria msc = new MyShardedCriteria(critId, mcf);
+    shardImpl.establishCriteria(msc);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mcf.createCriteriaCalledWith);
+    assertEquals(1, shardImpl.getCriteriaMap().size());
+    assertSame(crit, shardImpl.getCriteriaMap().get(critId));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getCriteriaEventMap().get(critId).isEmpty());
+
+    shardImpl.establishCriteria(msc);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mcf.createCriteriaCalledWith);
+    assertEquals(1, shardImpl.getCriteriaMap().size());
+    assertSame(crit, shardImpl.getCriteriaMap().get(critId));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getCriteriaEventMap().get(critId).isEmpty());
+  }
+
+  public void testEstablishMultipleCriteria() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+
+    MyCriteriaEvent event1 = new MyCriteriaEvent();
+    MyCriteriaEvent event2 = new MyCriteriaEvent();
+    CriteriaId critId1 = new CriteriaId(3);
+    Criteria crit1 = new CriteriaDefaultMock();
+    MyCriteriaFactory mcf1 = new MyCriteriaFactory(crit1);
+    MyShardedCriteria msc1 = new MyShardedCriteria(critId1, mcf1);
+
+    shardImpl.addCriteriaEvent(critId1, event1);
+    shardImpl.addCriteriaEvent(critId1, event2);
+
+    CriteriaId critId2 = new CriteriaId(4);
+    Criteria crit2 = new CriteriaDefaultMock();
+    MyCriteriaFactory mcf2 = new MyCriteriaFactory(crit2);
+    MyShardedCriteria msc2 = new MyShardedCriteria(critId2, mcf2);
+
+    shardImpl.establishCriteria(msc1);
+    shardImpl.establishCriteria(msc2);
+
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertEquals(2, shardImpl.getCriteriaMap().size());
+
+    assertNotNull(mcf1.createCriteriaCalledWith);
+    assertSame(crit1, shardImpl.getCriteriaMap().get(critId1));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getCriteriaEventMap().get(critId1).isEmpty());
+
+    assertNotNull(mcf2.createCriteriaCalledWith);
+    assertSame(crit2, shardImpl.getCriteriaMap().get(critId2));
+    assertNull(shardImpl.getCriteriaEventMap().get(critId2));
+
+    shardImpl.establishCriteria(msc1);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mcf1.createCriteriaCalledWith);
+    assertEquals(2, shardImpl.getCriteriaMap().size());
+    assertSame(crit1, shardImpl.getCriteriaMap().get(critId1));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+
+    assertNotNull(mcf2.createCriteriaCalledWith);
+    assertSame(crit2, shardImpl.getCriteriaMap().get(critId2));
+    assertNull(shardImpl.getCriteriaEventMap().get(critId2));
+
+    assertTrue(shardImpl.getCriteriaEventMap().get(critId1).isEmpty());
+  }
+
+  public void testAddQueryEvent() throws Exception {
+    ShardImpl shard = new ShardImpl(new ShardId(1), new SessionFactoryDefaultMock());
+    try {
+      shard.addQueryEvent(null, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    QueryId queryId = new QueryId(1);
+    try {
+      shard.addQueryEvent(queryId, null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    QueryEvent qe = new QueryEventDefaultMock();
+    try {
+      shard.addQueryEvent(null, qe);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    shard.addQueryEvent(queryId, qe);
+    assertNotNull(shard.getQueryEventMap());
+    assertEquals(1, shard.getQueryEventMap().size());
+    assertEquals(1, shard.getQueryEventMap().get(queryId).size());
+    assertSame(qe, shard.getQueryEventMap().get(queryId).get(0));
+
+    // now add another event to the same query
+    QueryEvent anotherQe = new QueryEventDefaultMock();
+    shard.addQueryEvent(queryId, anotherQe);
+    assertNotNull(shard.getQueryEventMap());
+    assertEquals(1, shard.getQueryEventMap().size());
+    assertEquals(2, shard.getQueryEventMap().get(queryId).size());
+    assertSame(qe, shard.getQueryEventMap().get(queryId).get(0));
+    assertSame(anotherQe, shard.getQueryEventMap().get(queryId).get(1));
+
+    // now add an event to a different query
+    QueryId anotherQueryId = new QueryId(3);
+    QueryEvent yetAnotherQe = new QueryEventDefaultMock();
+    shard.addQueryEvent(anotherQueryId, yetAnotherQe);
+    assertNotNull(shard.getQueryEventMap());
+    assertEquals(2, shard.getQueryEventMap().size());
+    assertEquals(2, shard.getQueryEventMap().get(queryId).size());
+    assertSame(qe, shard.getQueryEventMap().get(queryId).get(0));
+    assertSame(anotherQe, shard.getQueryEventMap().get(queryId).get(1));
+    assertEquals(1, shard.getQueryEventMap().get(anotherQueryId).size());
+    assertSame(yetAnotherQe, shard.getQueryEventMap().get(anotherQueryId).get(0));
+  }
+
+  public void testEstablishQueryNoEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    QueryId critId = new QueryId(3);
+    Query query = new QueryDefaultMock();
+    MyQueryFactory mqf = new MyQueryFactory(query);
+    MyShardedQuery msq = new MyShardedQuery(critId, mqf);
+    shardImpl.establishQuery(msq);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mqf.createQueryCalledWith);
+    assertEquals(1, shardImpl.getQueryMap().size());
+    assertSame(query, shardImpl.getQueryMap().get(critId));
+
+    shardImpl.establishQuery(msq);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mqf.createQueryCalledWith);
+    assertEquals(1, shardImpl.getQueryMap().size());
+    assertSame(query, shardImpl.getQueryMap().get(critId));
+  }
+
+  public void testEstablishQueryWithEvents() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+    MyQueryEvent event1 = new MyQueryEvent();
+    MyQueryEvent event2 = new MyQueryEvent();
+    QueryId queryId = new QueryId(3);
+    shardImpl.addQueryEvent(queryId, event1);
+    shardImpl.addQueryEvent(queryId, event2);
+    Query query = new QueryDefaultMock();
+    MyQueryFactory mqf = new MyQueryFactory(query);
+    MyShardedQuery msq = new MyShardedQuery(queryId, mqf);
+    shardImpl.establishQuery(msq);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mqf.createQueryCalledWith);
+    assertEquals(1, shardImpl.getQueryMap().size());
+    assertSame(query, shardImpl.getQueryMap().get(queryId));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getQueryEventMap().get(queryId).isEmpty());
+
+    shardImpl.establishQuery(msq);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mqf.createQueryCalledWith);
+    assertEquals(1, shardImpl.getQueryMap().size());
+    assertSame(query, shardImpl.getQueryMap().get(queryId));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getQueryEventMap().get(queryId).isEmpty());
+  }
+
+   public void testEstablishMultipleQuery() {
+    MySessionFactory sf = new MySessionFactory();
+    ShardImpl shardImpl = new ShardImpl(new ShardId(1), sf);
+
+    MyQueryEvent event1 = new MyQueryEvent();
+    MyQueryEvent event2 = new MyQueryEvent();
+    QueryId queryId1 = new QueryId(3);
+    Query query1 = new QueryDefaultMock();
+    MyQueryFactory mqf1 = new MyQueryFactory(query1);
+    MyShardedQuery msq1 = new MyShardedQuery(queryId1, mqf1);
+
+    shardImpl.addQueryEvent(queryId1, event1);
+    shardImpl.addQueryEvent(queryId1, event2);
+
+    QueryId queryId2 = new QueryId(4);
+    Query query2 = new QueryDefaultMock();
+    MyQueryFactory mqf2 = new MyQueryFactory(query2);
+    MyShardedQuery msq2 = new MyShardedQuery(queryId2, mqf2);
+
+    shardImpl.establishQuery(msq1);
+    shardImpl.establishQuery(msq2);
+
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertEquals(2, shardImpl.getQueryMap().size());
+
+    assertNotNull(mqf1.createQueryCalledWith);
+    assertSame(query1, shardImpl.getQueryMap().get(queryId1));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+    assertTrue(shardImpl.getQueryEventMap().get(queryId1).isEmpty());
+
+    assertNotNull(mqf2.createQueryCalledWith);
+    assertSame(query2, shardImpl.getQueryMap().get(queryId2));
+    assertNull(shardImpl.getQueryEventMap().get(queryId2));
+
+    shardImpl.establishQuery(msq1);
+    assertEquals(1, sf.numOpenSessionCalls);
+    assertNotNull(mqf1.createQueryCalledWith);
+    assertEquals(2, shardImpl.getQueryMap().size());
+    assertSame(query1, shardImpl.getQueryMap().get(queryId1));
+    assertEquals(1, event1.numOnEventCalls);
+    assertEquals(1, event2.numOnEventCalls);
+
+    assertNotNull(mqf2.createQueryCalledWith);
+    assertSame(query2, shardImpl.getQueryMap().get(queryId2));
+    assertNull(shardImpl.getQueryEventMap().get(queryId2));
+
+    assertTrue(shardImpl.getQueryEventMap().get(queryId1).isEmpty());
+  }
+
+  private static final class MyOpenSessionEvent extends OpenSessionEventDefaultMock {
+    private int numOnOpenSessionCalls = 0;
+    @Override
+    public void onOpenSession(org.hibernate.Session session) {
+      numOnOpenSessionCalls++;
+    }
+  }
+
+  private static final class MySessionFactory extends SessionFactoryDefaultMock {
+    private int numOpenSessionCalls;
+    private int numOpenSessionWithInterceptorCalls;
+
+    @Override
+    public org.hibernate.classic.Session openSession() throws HibernateException {
+      numOpenSessionCalls++;
+      return new SessionDefaultMock();
+    }
+
+    @Override
+    public org.hibernate.classic.Session openSession(Interceptor interceptor)
+        throws HibernateException {
+      numOpenSessionWithInterceptorCalls++;
+      return new SessionDefaultMock();
+    }
+  }
+
+  private static final class MyShardedCriteria extends ShardedCriteriaDefaultMock {
+    private final CriteriaId critId;
+    private final CriteriaFactory critFactory;
+
+    public MyShardedCriteria(CriteriaId critId, CriteriaFactory critFactory) {
+      this.critId = critId;
+      this.critFactory = critFactory;
+    }
+
+    @Override
+    public CriteriaId getCriteriaId() {
+      return critId;
+    }
+
+    @Override
+    public CriteriaFactory getCriteriaFactory() {
+      return critFactory;
+    }
+  }
+
+  private static final class MyCriteriaFactory extends CriteriaFactoryDefaultMock {
+    private org.hibernate.Session createCriteriaCalledWith;
+    private Criteria critToReturn;
+
+    public MyCriteriaFactory(Criteria critToReturn) {
+      this.critToReturn = critToReturn;
+    }
+
+    @Override
+    public Criteria createCriteria(org.hibernate.Session session) {
+      createCriteriaCalledWith = session;
+      return critToReturn;
+    }
+  }
+
+  private static final class MyCriteriaEvent implements CriteriaEvent {
+    private int numOnEventCalls;
+    public void onEvent(Criteria crit) {
+      numOnEventCalls++;
+    }
+  }
+
+   private static final class MyShardedQuery extends ShardedQueryDefaultMock {
+    private final QueryId queryId;
+    private final QueryFactory queryFactory;
+
+    public MyShardedQuery(QueryId queryId, QueryFactory queryFactory) {
+      this.queryId = queryId;
+      this.queryFactory = queryFactory;
+    }
+
+    @Override
+    public QueryId getQueryId() {
+      return queryId;
+    }
+
+    @Override
+    public QueryFactory getQueryFactory() {
+      return queryFactory;
+    }
+  }
+
+  public static final class MyQueryFactory extends QueryFactoryDefaultMock {
+    private org.hibernate.Session createQueryCalledWith;
+    private Query queryToReturn;
+
+    public MyQueryFactory(Query queryToReturn) {
+      this.queryToReturn = queryToReturn;
+    }
+
+    public Query createQuery(Session session) {
+      createQueryCalledWith = session;
+      return queryToReturn;
+    }
+  }
+
+  private static final class MyQueryEvent implements QueryEvent {
+    private int numOnEventCalls;
+    public void onEvent(Query query) {
+      numOnEventCalls++;
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardOperationDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardOperationDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardOperationDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ShardOperationDefaultMock<T> implements ShardOperation<T> {
+
+  public T execute(Shard shard) {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getOperationName() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedConfigurationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedConfigurationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedConfigurationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,133 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyFactoryDefaultMock;
+import org.hibernate.shards.session.ShardedSessionFactoryImpl;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.mapping.ManyToOne;
+import org.hibernate.mapping.OneToOne;
+import org.hibernate.mapping.Property;
+import org.hibernate.mapping.RootClass;
+import org.hibernate.mapping.Table;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ShardedConfigurationTest extends TestCase {
+
+  private MyShardStrategyFactory shardStrategyFactory;
+  private Configuration config;
+  private ShardedConfiguration shardedConfiguration;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+
+    shardStrategyFactory = new MyShardStrategyFactory();
+    config = new Configuration();
+    for(String prop : ShardedConfiguration.VARIABLE_PROPERTIES) {
+      config.setProperty(prop, "33");
+    }
+    config.setProperty(Environment.DIALECT, HSQLDialect.class.getName());
+
+    shardedConfiguration =
+        new ShardedConfiguration(
+            config,
+            Collections.singletonList(config),
+            shardStrategyFactory);
+  }
+
+  public void testBuildShardedSessionFactoryPreconditions() throws Exception {
+    List<Configuration> configList = Lists.newArrayList(config);
+    try {
+      new ShardedConfiguration(null, configList, shardStrategyFactory);
+      fail("Expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    Configuration config = new Configuration();
+    try {
+      new ShardedConfiguration(config, null, shardStrategyFactory);
+      fail("Expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    configList.clear();
+    try {
+      new ShardedConfiguration(config, configList, shardStrategyFactory);
+      fail("Expected iae");
+    } catch (IllegalArgumentException iae) {
+      // good
+    }
+  }
+
+  public void testShardIdRequired() {
+    Configuration config = new Configuration();
+    try {
+      shardedConfiguration.populatePrototypeWithVariableProperties(config);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+  }
+
+  public void testCopyPropertyToPrototype() {
+    Configuration prototype = new Configuration();
+    String copyMe = "copyMe";
+    config.setProperty(copyMe, "yamma");
+    ShardedConfiguration.copyPropertyToPrototype(prototype, config, copyMe);
+    assertEquals(config.getProperty(copyMe), prototype.getProperty(copyMe));
+  }
+
+  public void testBuildShardedSessionFactory() {
+    ShardedSessionFactoryImpl ssfi = (ShardedSessionFactoryImpl)shardedConfiguration.buildShardedSessionFactory();
+    assertNotNull(ssfi);
+  }
+
+  public void testRequiresShardLock() {
+    Property property = new Property();
+    assertFalse(shardedConfiguration.doesNotSupportTopLevelSave(property));
+    ManyToOne mto = new ManyToOne(new Table());
+    property.setValue(mto);
+    assertFalse(shardedConfiguration.doesNotSupportTopLevelSave(property));
+    OneToOne oto = new OneToOne(new Table(), new RootClass());
+    property.setValue(oto);
+    assertTrue(shardedConfiguration.doesNotSupportTopLevelSave(property));
+  }
+
+  private class MyShardStrategyFactory extends ShardStrategyFactoryDefaultMock {
+    @Override
+    public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+      return null;
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedSessionFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedSessionFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedSessionFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,339 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.session.ShardedSession;
+import org.hibernate.shards.session.ShardedSessionFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.StatelessSession;
+import org.hibernate.SessionFactory;
+import org.hibernate.MappingException;
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.proxy.EntityNotFoundDelegate;
+import org.hibernate.cfg.Settings;
+import org.hibernate.exception.SQLExceptionConverter;
+import org.hibernate.cache.QueryCache;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cache.Cache;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.type.Type;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.classic.Session;
+import org.hibernate.engine.FilterDefinition;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.NamedQueryDefinition;
+import org.hibernate.engine.NamedSQLQueryDefinition;
+import org.hibernate.engine.ResultSetMappingDefinition;
+import org.hibernate.engine.query.QueryPlanCache;
+import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.metadata.CollectionMetadata;
+import org.hibernate.stat.Statistics;
+import org.hibernate.stat.StatisticsImplementor;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionFactoryDefaultMock implements ShardedSessionFactoryImplementor {
+
+  public Map<SessionFactoryImplementor, Set<ShardId>> getSessionFactoryShardIdMap() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(Connection connection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardedSession openSession(Interceptor interceptor)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(Connection connection, Interceptor interceptor) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardedSession openSession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session getCurrentSession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata(Class persistentClass)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata(String entityName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public CollectionMetadata getCollectionMetadata(String roleName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllClassMetadata() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllCollectionMetadata() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Statistics getStatistics() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void close() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isClosed() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Class persistentClass) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Class persistentClass, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictEntity(String entityName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictEntity(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictCollection(String roleName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictCollection(String roleName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictQueries() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictQueries(String cacheRegion) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatelessSession openStatelessSession() {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatelessSession openStatelessSession(Connection connection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set getDefinedFilterNames() {
+    throw new UnsupportedOperationException();
+  }
+
+  public FilterDefinition getFilterDefinition(String filterName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Reference getReference() throws NamingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionImplementor openControlSession() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean containsFactory(SessionFactoryImplementor factory) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<SessionFactory> getSessionFactories() {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityPersister getEntityPersister(String entityName)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public CollectionPersister getCollectionPersister(String role)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Dialect getDialect() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Interceptor getInterceptor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryPlanCache getQueryPlanCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getReturnTypes(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getReturnAliases(String queryString)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ConnectionProvider getConnectionProvider() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getImplementors(String className) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getImportedClassName(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public TransactionManager getTransactionManager() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryCache getQueryCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryCache getQueryCache(String regionName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public UpdateTimestampsCache getUpdateTimestampsCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatisticsImplementor getStatisticsImplementor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public NamedQueryDefinition getNamedQuery(String queryName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ResultSetMappingDefinition getResultSetMapping(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Cache getSecondLevelCacheRegion(String regionName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllSecondLevelCacheRegions() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLExceptionConverter getSQLExceptionConverter() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Settings getSettings() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openTemporarySession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(final Connection connection,
+      final boolean flushBeforeCompletionEnabled,
+      final boolean autoCloseSessionEnabled,
+      final ConnectionReleaseMode connectionReleaseMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set getCollectionRolesByEntityParticipant(String entityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getIdentifierType(String className) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getIdentifierPropertyName(String className)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getReferencedPropertyType(String className, String propertyName)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityNotFoundDelegate getEntityNotFoundDelegate() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLFunctionRegistry getSqlFunctionRegistry() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardedSessionFactory getSessionFactory(List<ShardId> shardIds,
+      ShardStrategyFactory shardStrategyFactory) {
+    throw new UnsupportedOperationException();
+  }
+}
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedTransactionDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedTransactionDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/ShardedTransactionDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards;
+
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+import javax.transaction.Synchronization;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedTransactionDefaultMock implements ShardedTransaction {
+
+  public void setupTransaction(Session session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void begin() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void commit() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void rollback() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean wasRolledBack() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean wasCommitted() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isActive() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void registerSynchronization(Synchronization synchronization)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setTimeout(int seconds) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddCriterionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddCriterionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddCriterionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Criterion;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class AddCriterionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    AddCriterionEvent event = new AddCriterionEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria add(Criterion criterion) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddOrderEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddOrderEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/AddOrderEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Order;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class AddOrderEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    AddOrderEvent event = new AddOrderEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria addOrder(Order order) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateAliasEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateAliasEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateAliasEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class CreateAliasEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    CreateAliasEvent event = new CreateAliasEvent(null, null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria createAlias(String associationPath, String alias)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+  public void testOnOpenSessionWithJoinType() {
+    CreateAliasEvent event = new CreateAliasEvent(null, null, 0);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria createAlias(String associationPath, String alias,
+          int joinType) throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateSubcriteriaEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateSubcriteriaEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CreateSubcriteriaEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class CreateSubcriteriaEventTest extends TestCase {
+  public void testOnEvent() {
+    final Criteria[] calledWithCrit = {null};
+    final SubcriteriaFactory[] calledWithFactory = {null};
+
+    ShardedSubcriteriaImpl.SubcriteriaRegistrar provider = new ShardedSubcriteriaImpl.SubcriteriaRegistrar() {
+      public void establishSubcriteria(
+          Criteria parentCriteria,
+          SubcriteriaFactory subcriteriaFactory) {
+        calledWithCrit[0] = parentCriteria;
+        calledWithFactory[0] = subcriteriaFactory;
+      }
+    };
+
+    SubcriteriaFactory factory = new SubcriteriaFactoryDefaultMock();
+    CreateSubcriteriaEvent cse = new CreateSubcriteriaEvent(factory, provider);
+    Criteria crit = new CriteriaDefaultMock();
+    cse.onEvent(crit);
+    assertSame(crit, calledWithCrit[0]);
+    assertSame(factory, calledWithFactory[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaEventDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaEventDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaEventDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaEventDefaultMock implements CriteriaEvent {
+
+  public void onEvent(Criteria crit) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaFactoryDefaultMock implements CriteriaFactory {
+
+  public Criteria createCriteria(Session session) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/CriteriaFactoryImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaFactoryImplTest extends TestCase {
+
+  public void testOnOpenSessionAssocPath() {
+    CriteriaFactoryImpl cfi = new CriteriaFactoryImpl("entity name");
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public Criteria createCriteria(String entityName)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    cfi.createCriteria(session);
+    assertTrue(called[0]);
+  }
+
+  public void testOnOpenSessionAssocPathAndJoinType() {
+    CriteriaFactoryImpl cfi = new CriteriaFactoryImpl("entity name", "alias");
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public Criteria createCriteria(String entityName, String alias)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    cfi.createCriteria(session);
+    assertTrue(called[0]);
+  }
+
+  public void testOnOpenSessionAssocPathAndAlias() {
+    CriteriaFactoryImpl cfi = new CriteriaFactoryImpl(String.class);
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public Criteria createCriteria(Class pc)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    cfi.createCriteria(session);
+    assertTrue(called[0]);
+  }
+
+  public void testOnOpenSessionAssocPathAndAliasAndJoinType() {
+    CriteriaFactoryImpl cfi = new CriteriaFactoryImpl(String.class, "alias");
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public Criteria createCriteria(Class pc, String alias)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    cfi.createCriteria(session);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.CacheMode;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetCacheModeEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetCacheModeEvent event = new SetCacheModeEvent(CacheMode.GET);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setCacheMode(CacheMode cacheMode) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheRegionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheRegionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheRegionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetCacheRegionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetCacheRegionEvent event = new SetCacheRegionEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setCacheRegion(String cacheRegion) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheableEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheableEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCacheableEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetCacheableEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetCacheableEvent event = new SetCacheableEvent(true);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setCacheable(boolean cacheable) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCommentEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCommentEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetCommentEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetCommentEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetCommentEvent event = new SetCommentEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setComment(String comment) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.HibernateException;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetFetchModeEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetFetchModeEvent event = new SetFetchModeEvent(null, FetchMode.DEFAULT);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setFetchMode(String associationPath, FetchMode mode)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchSizeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchSizeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFetchSizeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetFetchSizeEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetFetchSizeEvent event = new SetFetchSizeEvent(33);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setFetchSize(int fetchSize) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFirstResultEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFirstResultEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFirstResultEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetFirstResultEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetFirstResultEvent event = new SetFirstResultEvent(33);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setFirstResult(int firstResult) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFlushModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFlushModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetFlushModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.FlushMode;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetFlushModeEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetFlushModeEvent event = new SetFlushModeEvent(FlushMode.ALWAYS);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setFlushMode(FlushMode flushMode) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetLockModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetLockModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetLockModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.LockMode;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetLockModeEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetLockModeEvent event = new SetLockModeEvent(LockMode.NONE);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setLockMode(LockMode lockMode) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+  public void testOnOpenSessionWithAlias() {
+    SetLockModeEvent event = new SetLockModeEvent(LockMode.NONE, null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setLockMode(String alias, LockMode lockMode) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetMaxResultsEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetMaxResultsEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetMaxResultsEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetMaxResultsEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetMaxResultsEvent event = new SetMaxResultsEvent(22);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setMaxResults(int maxResults) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetProjectionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetProjectionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetProjectionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Projection;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetProjectionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetProjectionEvent event = new SetProjectionEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setProjection(Projection projection) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetResultTransformerEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetResultTransformerEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetResultTransformerEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.transform.ResultTransformer;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetResultTransformerEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetResultTransformerEvent event = new SetResultTransformerEvent(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setResultTransformer(ResultTransformer resultTransformer) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetTimeoutEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetTimeoutEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SetTimeoutEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetTimeoutEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetTimeoutEvent event = new SetTimeoutEvent(23);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria setTimeout(int timeout) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(crit);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedCriteriaDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedCriteriaDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedCriteriaDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,164 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.FlushMode;
+import org.hibernate.CacheMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.ScrollMode;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedCriteriaDefaultMock implements ShardedCriteria {
+
+  public CriteriaId getCriteriaId() {
+    throw new UnsupportedOperationException();
+  }
+
+  public CriteriaFactory getCriteriaFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getAlias() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setProjection(Projection projection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria add(Criterion criterion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria addOrder(Order order) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFetchMode(String associationPath, FetchMode mode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setLockMode(LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setLockMode(String alias, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createAlias(String associationPath, String alias)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createAlias(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, int joinType)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, String alias)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setResultTransformer(ResultTransformer resultTransformer) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setMaxResults(int maxResults) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFirstResult(int firstResult) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFetchSize(int fetchSize) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setTimeout(int timeout) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheable(boolean cacheable) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheRegion(String cacheRegion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setComment(String comment) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(ScrollMode scrollMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedSubcriteriaImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedSubcriteriaImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/ShardedSubcriteriaImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,147 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardDefaultMock;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Sets;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ShardedSubcriteriaImplTest extends TestCase {
+
+  public void testInit() {
+    final int[] next = {0};
+    class MyShard extends ShardDefaultMock {
+      @Override
+      public Set<ShardId> getShardIds() {
+        return Sets.newHashSet(new ShardId(next[0]++));
+      }
+    }
+    Shard s1 = new MyShard();
+    Shard s2 = new MyShard();
+    Shard s3 = new MyShard();
+    List<Shard> shards = Lists.newArrayList(s1, s2, s3);
+    ShardedSubcriteriaImpl ss = new ShardedSubcriteriaImpl(shards,  new ShardedCriteriaDefaultMock());
+    assertEquals(shards.size(), ss.getShardToCriteriaMap().size());
+    assertEquals(shards.size(), ss.getShardToEventListMap().size());
+  }
+
+  public void testListDelegatesToParent() {
+    List<Shard> shards = Lists.<Shard>newArrayList(new ShardDefaultMock());
+    final boolean[] called = {false};
+    ShardedCriteria parent = new ShardedCriteriaDefaultMock() {
+      @Override
+      public List list() throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    ShardedSubcriteriaImpl ss = new ShardedSubcriteriaImpl(shards,  parent);
+    ss.list();
+    assertTrue(called[0]);
+  }
+
+  public void testUniqueResultDelegatesToParent() {
+    List<Shard> shards = Lists.<Shard>newArrayList(new ShardDefaultMock());
+    final boolean[] called = {false};
+    ShardedCriteria parent = new ShardedCriteriaDefaultMock() {
+      @Override
+      public Object uniqueResult() throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    ShardedSubcriteriaImpl ss = new ShardedSubcriteriaImpl(shards,  parent);
+    ss.uniqueResult();
+    assertTrue(called[0]);
+  }
+
+  public void testScrollDelegatesToParent() {
+    List<Shard> shards = Lists.<Shard>newArrayList(new ShardDefaultMock());
+    final boolean[] scrollNoArgsCalled = {false};
+    final boolean[] scroll1ArgCalled = {false};
+    ShardedCriteria parent = new ShardedCriteriaDefaultMock() {
+      @Override
+      public ScrollableResults scroll() throws HibernateException {
+        scrollNoArgsCalled[0] = true;
+        return null;
+      }
+
+      @Override
+      public ScrollableResults scroll(ScrollMode scrollMode)
+          throws HibernateException {
+        scroll1ArgCalled[0] = true;
+        return null;
+      }
+    };
+    ShardedSubcriteriaImpl ss = new ShardedSubcriteriaImpl(shards,  parent);
+    ss.scroll();
+    assertTrue(scrollNoArgsCalled[0]);
+    assertFalse(scroll1ArgCalled[0]);
+
+    scrollNoArgsCalled[0] = false;
+    ss.scroll(ScrollMode.FORWARD_ONLY);
+    assertFalse(scrollNoArgsCalled[0]);
+    assertTrue(scroll1ArgCalled[0]);
+  }
+
+  public void testEstablishCriteria() {
+    Shard shard = new ShardDefaultMock() {
+      @Override
+      public Set<ShardId> getShardIds() {
+        return Sets.newHashSet(new ShardId(0));
+      }
+    };
+    Shard someOtherShard = new ShardDefaultMock();
+    List<Shard> shards = Lists.newArrayList(shard, someOtherShard);
+    ShardedCriteria parent = new ShardedCriteriaDefaultMock();
+    ShardedSubcriteriaImpl ss = new ShardedSubcriteriaImpl(shards,  parent);
+    ss.getShardToEventListMap().get(shard).add(new CriteriaEventDefaultMock());
+    final Criteria subcritToReturn = new CriteriaDefaultMock();
+    SubcriteriaFactory factory = new SubcriteriaFactoryDefaultMock() {
+      @Override
+      public Criteria createSubcriteria(Criteria parent,
+          Iterable<CriteriaEvent> events) {
+        return subcritToReturn;
+      }
+    };
+    Criteria parentCrit = new CriteriaDefaultMock();
+    ss.getSubcriteriaRegistrar(shard).establishSubcriteria(parentCrit, factory);
+    ss.getSubcriteriaRegistrar(someOtherShard).establishSubcriteria(parentCrit, factory);
+    assertTrue(ss.getShardToEventListMap().get(shard).isEmpty());
+    assertTrue(ss.getShardToEventListMap().get(someOtherShard).isEmpty());
+    assertSame(subcritToReturn, ss.getShardToCriteriaMap().get(shard));
+    assertSame(subcritToReturn, ss.getShardToCriteriaMap().get(someOtherShard));
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.Criteria;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class SubcriteriaFactoryDefaultMock implements SubcriteriaFactory {
+
+  public Criteria createSubcriteria(Criteria parent,
+      Iterable<CriteriaEvent> events) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/criteria/SubcriteriaFactoryImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,136 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.criteria;
+
+import org.hibernate.shards.defaultmock.CriteriaDefaultMock;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.HibernateException;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SubcriteriaFactoryImplTest extends TestCase {
+
+  private static final Iterable<CriteriaEvent> NO_EVENTS = Lists.newArrayList();
+
+  public void testOnOpenSessionAssocPath() {
+    SubcriteriaFactoryImpl sfi = new SubcriteriaFactoryImpl(null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria createCriteria(String associationPath)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    sfi.createSubcriteria(crit, NO_EVENTS);
+    assertTrue(called[0]);
+    called[0] = false;
+
+    MyCriteriaEvent mce1 = new MyCriteriaEvent();
+    MyCriteriaEvent mce2 = new MyCriteriaEvent();
+    sfi.createSubcriteria(crit, Lists.<CriteriaEvent>newArrayList(mce1, mce2));
+    assertTrue(called[0]);
+    assertEquals(1, mce1.numOnEventCalls);
+    assertEquals(1, mce2.numOnEventCalls);
+  }
+
+  public void testOnOpenSessionAssocPathAndJoinType() {
+    SubcriteriaFactoryImpl sfi = new SubcriteriaFactoryImpl(null, 0);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+
+      @Override
+      public Criteria createCriteria(String associationPath, int joinType)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    sfi.createSubcriteria(crit, NO_EVENTS);
+    assertTrue(called[0]);
+    called[0] = false;
+
+    MyCriteriaEvent mce1 = new MyCriteriaEvent();
+    MyCriteriaEvent mce2 = new MyCriteriaEvent();
+    sfi.createSubcriteria(crit, Lists.<CriteriaEvent>newArrayList(mce1, mce2));
+    assertTrue(called[0]);
+    assertEquals(1, mce1.numOnEventCalls);
+    assertEquals(1, mce2.numOnEventCalls);
+  }
+
+  public void testOnOpenSessionAssocPathAndAlias() {
+    SubcriteriaFactoryImpl sfi = new SubcriteriaFactoryImpl(null, null);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria createCriteria(String associationPath, String alias)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    sfi.createSubcriteria(crit, NO_EVENTS);
+    assertTrue(called[0]);
+    called[0] = false;
+
+    MyCriteriaEvent mce1 = new MyCriteriaEvent();
+    MyCriteriaEvent mce2 = new MyCriteriaEvent();
+    sfi.createSubcriteria(crit, Lists.<CriteriaEvent>newArrayList(mce1, mce2));
+    assertTrue(called[0]);
+    assertEquals(1, mce1.numOnEventCalls);
+    assertEquals(1, mce2.numOnEventCalls);
+  }
+
+  public void testOnOpenSessionAssocPathAndAliasAndJoinType() {
+    SubcriteriaFactoryImpl sfi = new SubcriteriaFactoryImpl(null, null, 0);
+    final boolean[] called = {false};
+    Criteria crit = new CriteriaDefaultMock() {
+      @Override
+      public Criteria createCriteria(String associationPath, String alias, int joinType)
+          throws HibernateException {
+        called[0] = true;
+        return null;
+      }
+    };
+    sfi.createSubcriteria(crit, NO_EVENTS);
+    assertTrue(called[0]);
+    called[0] = false;
+
+    MyCriteriaEvent mce1 = new MyCriteriaEvent();
+    MyCriteriaEvent mce2 = new MyCriteriaEvent();
+    sfi.createSubcriteria(crit, Lists.<CriteriaEvent>newArrayList(mce1, mce2));
+    assertTrue(called[0]);
+    assertEquals(1, mce1.numOnEventCalls);
+    assertEquals(1, mce2.numOnEventCalls);
+  }
+
+  private static final class MyCriteriaEvent implements CriteriaEvent {
+    private int numOnEventCalls;
+    public void onEvent(Criteria crit) {
+      numOnEventCalls++;
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/ClassMetadataDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/ClassMetadataDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/ClassMetadataDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.type.Type;
+import org.hibernate.HibernateException;
+import org.hibernate.EntityMode;
+import org.hibernate.engine.SessionImplementor;
+
+import java.util.Map;
+import java.io.Serializable;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ClassMetadataDefaultMock implements ClassMetadata {
+
+  public String getEntityName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getIdentifierPropertyName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getPropertyNames() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getIdentifierType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getPropertyTypes() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getPropertyType(String propertyName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasProxy() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isMutable() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isVersioned() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getVersionProperty() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyNullability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyLaziness() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasIdentifierProperty() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasNaturalIdentifier() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] getNaturalIdentifierProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasSubclasses() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isInherited() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getPropertyValuesToInsert(Object entity, Map mergeMap,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Class getMappedClass(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object instantiate(Serializable id, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getPropertyValue(Object object, String propertyName,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getPropertyValues(Object entity, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setPropertyValue(Object object, String propertyName, Object value,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setPropertyValues(Object object, Object[] values,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getIdentifier(Object entity, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setIdentifier(Object object, Serializable id,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean implementsLifecycle(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean implementsValidatable(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getVersion(Object object, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/CriteriaDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/CriteriaDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/CriteriaDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,156 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.Criteria;
+import org.hibernate.FetchMode;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.FlushMode;
+import org.hibernate.CacheMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.ScrollMode;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Order;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class CriteriaDefaultMock implements Criteria {
+
+  public String getAlias() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setProjection(Projection projection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria add(Criterion criterion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria addOrder(Order order) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFetchMode(String associationPath, FetchMode mode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setLockMode(LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setLockMode(String alias, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createAlias(String associationPath, String alias)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createAlias(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, int joinType)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, String alias)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String associationPath, String alias,
+      int joinType) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setResultTransformer(ResultTransformer resultTransformer) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setMaxResults(int maxResults) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFirstResult(int firstResult) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFetchSize(int fetchSize) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setTimeout(int timeout) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheable(boolean cacheable) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheRegion(String cacheRegion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setComment(String comment) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(ScrollMode scrollMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/EntityPersisterDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/EntityPersisterDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/EntityPersisterDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,443 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.MappingException;
+import org.hibernate.HibernateException;
+import org.hibernate.LockMode;
+import org.hibernate.EntityMode;
+import org.hibernate.tuple.entity.EntityMetamodel;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.cache.CacheConcurrencyStrategy;
+import org.hibernate.cache.entry.CacheEntryStructure;
+import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.type.Type;
+import org.hibernate.type.VersionType;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.CascadeStyle;
+import org.hibernate.engine.ValueInclusion;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Comparator;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class EntityPersisterDefaultMock implements EntityPersister {
+
+  public void postInstantiate() throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionFactoryImplementor getFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getRootEntityName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getEntityName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isSubclassEntityName(String entityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable[] getPropertySpaces() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable[] getQuerySpaces() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasProxy() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasCollections() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasMutableProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasSubselectLoadableCollections() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasCascades() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isMutable() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isInherited() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isIdentifierAssignedByInsert() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getPropertyType(String propertyName) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] findDirty(Object[] x, Object[] y, Object owner,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] findModified(Object[] old, Object[] current, Object object,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasIdentifierProperty() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean canExtractIdOutOfEntity() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isVersioned() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Comparator getVersionComparator() {
+    throw new UnsupportedOperationException();
+  }
+
+  public VersionType getVersionType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getVersionProperty() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasNaturalIdentifier() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] getNaturalIdentifierProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getNaturalIdentifierSnapshot(Serializable id,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public IdentifierGenerator getIdentifierGenerator()
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasLazyProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(Serializable id, Object optionalObject, LockMode lockMode,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lock(Serializable id, Object version, Object object,
+      LockMode lockMode, SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void insert(Serializable id, Object[] fields, Object object,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable insert(Object[] fields, Object object,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(Serializable id, Object version, Object object,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Serializable id, Object[] fields, int[] dirtyFields,
+      boolean hasDirtyCollection, Object[] oldFields, Object oldVersion,
+      Object object, Object rowId, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getPropertyTypes() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getPropertyNames() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyInsertability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyInsertGeneration() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyUpdateGeneration() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyUpdateability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyCheckability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyNullability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyVersionability() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] getPropertyLaziness() {
+    throw new UnsupportedOperationException();
+  }
+
+  public CascadeStyle[] getPropertyCascadeStyles() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getIdentifierType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getIdentifierPropertyName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isCacheInvalidationRequired() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isLazyPropertiesCacheable() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public CacheConcurrencyStrategy getCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public CacheEntryStructure getCacheEntryStructure() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isBatchLoadable() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isSelectBeforeUpdateRequired() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getDatabaseSnapshot(Serializable id,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getCurrentVersion(Serializable id, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object forceVersionIncrement(Serializable id, Object currentVersion,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityMode guessEntityMode(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isInstrumented(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasInsertGeneratedProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasUpdateGeneratedProperties() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isVersionPropertyGenerated() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterInitialize(Object entity, boolean lazyPropertiesAreUnfetched,
+      SessionImplementor session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterReassociate(Object entity, SessionImplementor session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object createProxy(Serializable id, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Boolean isTransient(Object object, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getPropertyValuesToInsert(Object object, Map mergeMap,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void processInsertGeneratedProperties(Serializable id, Object entity,
+      Object[] state, SessionImplementor session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void processUpdateGeneratedProperties(Serializable id, Object entity,
+      Object[] state, SessionImplementor session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Class getMappedClass(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean implementsLifecycle(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean implementsValidatable(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Class getConcreteProxyClass(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setPropertyValues(Object object, Object[] values,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setPropertyValue(Object object, int i, Object value,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object[] getPropertyValues(Object object, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getPropertyValue(Object object, int i, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getPropertyValue(Object object, String propertyName,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getIdentifier(Object object, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setIdentifier(Object object, Serializable id,
+      EntityMode entityMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getVersion(Object object, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object instantiate(Serializable id, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isInstance(Object object, EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean hasUninitializedLazyProperties(Object object,
+      EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void resetIdentifier(Object entity, Serializable currentId,
+      Object currentVersion, EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityPersister getSubclassEntityPersister(Object instance,
+      SessionFactoryImplementor factory, EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityMetamodel getEntityMetamodel() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ValueInclusion[] getPropertyInsertGenerationInclusions() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ValueInclusion[] getPropertyUpdateGenerationInclusions() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/InterceptorDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/InterceptorDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/InterceptorDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,117 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.Interceptor;
+import org.hibernate.CallbackException;
+import org.hibernate.EntityMode;
+import org.hibernate.Transaction;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class InterceptorDefaultMock implements Interceptor {
+
+  public boolean onLoad(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean onFlushDirty(Object entity, Serializable id,
+      Object[] currentState, Object[] previousState, String[] propertyNames,
+      Type[] types) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean onSave(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void onDelete(Object entity, Serializable id, Object[] state,
+      String[] propertyNames, Type[] types) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void onCollectionRecreate(Object collection, Serializable key)
+      throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void onCollectionRemove(Object collection, Serializable key)
+      throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void onCollectionUpdate(Object collection, Serializable key)
+      throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void preFlush(Iterator entities) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void postFlush(Iterator entities) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Boolean isTransient(Object entity) {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] findDirty(Object entity, Serializable id, Object[] currentState,
+      Object[] previousState, String[] propertyNames, Type[] types) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object instantiate(String entityName, EntityMode entityMode,
+      Serializable id) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getEntityName(Object object) throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getEntity(String entityName, Serializable id)
+      throws CallbackException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterTransactionBegin(Transaction tx) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void beforeTransactionCompletion(Transaction tx) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterTransactionCompletion(Transaction tx) {
+    throw new UnsupportedOperationException();
+  }
+
+  public String onPrepareStatement(String sql) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/QueryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/QueryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/QueryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,334 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.*;
+import org.hibernate.transform.ResultTransformer;
+import org.hibernate.type.Type;
+
+import java.util.*;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class QueryDefaultMock implements Query {
+
+  public String getQueryString() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getReturnTypes() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getReturnAliases() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getNamedParameters() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int executeUpdate() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setMaxResults(int maxResults) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFirstResult(int firstResult) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setReadOnly(boolean readOnly) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheable(boolean cacheable) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheRegion(String cacheRegion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimeout(int timeout) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFetchSize(int fetchSize) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLockMode(String alias, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setComment(String comment) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(int position, Object val, Type type) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(String name, Object val, Type type) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(int position, Object val) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(String name, Object val) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameters(Object[] values, Type[] types) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Collection vals) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Object[] vals, Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Object[] vals) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setProperties(Object bean) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setString(int position, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCharacter(int position, char val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBoolean(int position, boolean val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setByte(int position, byte val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setShort(int position, short val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setInteger(int position, int val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLong(int position, long val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFloat(int position, float val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDouble(int position, double val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBinary(int position, byte[] val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setText(int position, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setSerializable(int position, Serializable val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLocale(int position, Locale locale) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigDecimal(int position, BigDecimal number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigInteger(int position, BigInteger number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDate(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTime(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimestamp(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendar(int position, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendarDate(int position, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setString(String name, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCharacter(String name, char val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBoolean(String name, boolean val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setByte(String name, byte val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setShort(String name, short val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setInteger(String name, int val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLong(String name, long val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFloat(String name, float val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDouble(String name, double val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBinary(String name, byte[] val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setText(String name, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setSerializable(String name, Serializable val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLocale(String name, Locale locale) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigDecimal(String name, BigDecimal number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigInteger(String name, BigInteger number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDate(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTime(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimestamp(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendar(String name, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendarDate(String name, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setEntity(int position, Object val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setEntity(String name, Object val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setResultTransformer(ResultTransformer transformer) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setProperties(Map bean) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,429 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.classic.Session;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.EntityMode;
+import org.hibernate.FlushMode;
+import org.hibernate.CacheMode;
+import org.hibernate.SessionFactory;
+import org.hibernate.LockMode;
+import org.hibernate.ReplicationMode;
+import org.hibernate.Transaction;
+import org.hibernate.Criteria;
+import org.hibernate.SQLQuery;
+import org.hibernate.Filter;
+import org.hibernate.stat.SessionStatistics;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collection;
+import java.sql.Connection;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SessionDefaultMock implements Session {
+
+  public Object saveOrUpdateCopy(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(String entityName, Object object,
+      Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter, Object value,
+      Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter, Object[] values,
+      Type[] types) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createSQLQuery(String sql, String returnAlias,
+      Class returnClass) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createSQLQuery(String sql, String[] returnAliases,
+      Class[] returnClasses) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void save(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void save(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityMode getEntityMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public org.hibernate.Session getSession(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void flush() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public FlushMode getFlushMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public CacheMode getCacheMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionFactory getSessionFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection connection() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection close() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void cancelQuery() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isOpen() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isConnected() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isDirty() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getIdentifier(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean contains(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(Class theClass, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(String entityName, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(Class theClass, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void load(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicate(Object object, ReplicationMode replicationMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicate(String entityName, Object object,
+      ReplicationMode replicationMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object merge(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object merge(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void persist(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void persist(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lock(Object object, LockMode lockMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lock(String entityName, Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void refresh(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void refresh(Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public LockMode getCurrentLockMode(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Transaction beginTransaction() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Transaction getTransaction() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(Class persistentClass) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(Class persistentClass, String alias) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String entityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String entityName, String alias) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createQuery(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLQuery createSQLQuery(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createFilter(Object collection, String queryString)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getNamedQuery(String queryName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class clazz, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class clazz, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getEntityName(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Filter enableFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Filter getEnabledFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void disableFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionStatistics getStatistics() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setReadOnly(Object entity, boolean readOnly) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection disconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void reconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void reconnect(Connection connection) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,309 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.ConnectionReleaseMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.MappingException;
+import org.hibernate.StatelessSession;
+import org.hibernate.proxy.EntityNotFoundDelegate;
+import org.hibernate.cache.Cache;
+import org.hibernate.cache.QueryCache;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cfg.Settings;
+import org.hibernate.classic.Session;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.engine.FilterDefinition;
+import org.hibernate.engine.NamedQueryDefinition;
+import org.hibernate.engine.NamedSQLQueryDefinition;
+import org.hibernate.engine.ResultSetMappingDefinition;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.query.QueryPlanCache;
+import org.hibernate.exception.SQLExceptionConverter;
+import org.hibernate.id.IdentifierGenerator;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.metadata.CollectionMetadata;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.stat.Statistics;
+import org.hibernate.stat.StatisticsImplementor;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.sql.Connection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SessionFactoryDefaultMock implements SessionFactoryImplementor {
+
+  public Session openSession(Connection connection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(Interceptor interceptor)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(Connection connection, Interceptor interceptor) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session getCurrentSession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata(Class persistentClass)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ClassMetadata getClassMetadata(String entityName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public CollectionMetadata getCollectionMetadata(String roleName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllClassMetadata() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllCollectionMetadata() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Statistics getStatistics() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void close() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isClosed() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Class persistentClass) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Class persistentClass, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictEntity(String entityName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictEntity(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictCollection(String roleName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictCollection(String roleName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictQueries() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evictQueries(String cacheRegion) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatelessSession openStatelessSession() {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatelessSession openStatelessSession(Connection connection) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set getDefinedFilterNames() {
+    throw new UnsupportedOperationException();
+  }
+
+  public FilterDefinition getFilterDefinition(String filterName)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Reference getReference() throws NamingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityPersister getEntityPersister(String entityName)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public CollectionPersister getCollectionPersister(String role)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Dialect getDialect() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Interceptor getInterceptor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryPlanCache getQueryPlanCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getReturnTypes(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getReturnAliases(String queryString)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ConnectionProvider getConnectionProvider() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getImplementors(String className) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getImportedClassName(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public TransactionManager getTransactionManager() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryCache getQueryCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryCache getQueryCache(String regionName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public UpdateTimestampsCache getUpdateTimestampsCache() {
+    throw new UnsupportedOperationException();
+  }
+
+  public StatisticsImplementor getStatisticsImplementor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public NamedQueryDefinition getNamedQuery(String queryName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public NamedSQLQueryDefinition getNamedSQLQuery(String queryName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ResultSetMappingDefinition getResultSetMapping(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public IdentifierGenerator getIdentifierGenerator(String rootEntityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Cache getSecondLevelCacheRegion(String regionName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getAllSecondLevelCacheRegions() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLExceptionConverter getSQLExceptionConverter() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Settings getSettings() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openTemporarySession() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session openSession(final Connection connection,
+      final boolean flushBeforeCompletionEnabled,
+      final boolean autoCloseSessionEnabled,
+      final ConnectionReleaseMode connectionReleaseMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Set getCollectionRolesByEntityParticipant(String entityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getIdentifierType(String className) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getIdentifierPropertyName(String className)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getReferencedPropertyType(String className, String propertyName)
+      throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityNotFoundDelegate getEntityNotFoundDelegate() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLFunctionRegistry getSqlFunctionRegistry() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionImplementorDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionImplementorDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/SessionImplementorDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,285 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.QueryParameters;
+import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.PersistenceContext;
+import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.Interceptor;
+import org.hibernate.HibernateException;
+import org.hibernate.ScrollableResults;
+import org.hibernate.ScrollMode;
+import org.hibernate.Transaction;
+import org.hibernate.EntityMode;
+import org.hibernate.CacheMode;
+import org.hibernate.FlushMode;
+import org.hibernate.Query;
+import org.hibernate.event.EventListeners;
+import org.hibernate.type.Type;
+import org.hibernate.loader.custom.CustomQuery;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.impl.CriteriaImpl;
+import org.hibernate.jdbc.Batcher;
+import org.hibernate.jdbc.JDBCContext;
+import org.hibernate.collection.PersistentCollection;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+import java.sql.Connection;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class SessionImplementorDefaultMock implements SessionImplementor {
+
+  public void setAutoClear(boolean enabled) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Interceptor getInterceptor() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isTransactionInProgress() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void initializeCollection(PersistentCollection collection,
+      boolean writing) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object internalLoad(String entityName, Serializable id, boolean eager,
+      boolean nullable) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object immediateLoad(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public long getTimestamp() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionFactoryImplementor getFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Batcher getBatcher() {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list(String query, QueryParameters queryParameters)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query, QueryParameters queryParameters)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(String query, QueryParameters queryParameters)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(CriteriaImpl criteria,
+      ScrollMode scrollMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list(CriteriaImpl criteria) {
+    throw new UnsupportedOperationException();
+  }
+
+  public List listFilter(Object collection, String filter,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterateFilter(Object collection, String filter,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityPersister getEntityPersister(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getEntityUsingInterceptor(EntityKey key)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterTransactionCompletion(boolean successful, Transaction tx) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void beforeTransactionCompletion(Transaction tx) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getContextEntityIdentifier(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public String bestGuessEntityName(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public String guessEntityName(Object entity) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object instantiate(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List listCustomQuery(CustomQuery customQuery,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scrollCustomQuery(CustomQuery customQuery,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list(NativeSQLQuerySpecification spec,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(NativeSQLQuerySpecification spec,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object getFilterParameterValue(String filterParameterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getFilterParameterType(String filterParameterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Map getEnabledFilters() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getDontFlushFromFind() {
+    throw new UnsupportedOperationException();
+  }
+
+  public EventListeners getListeners() {
+    throw new UnsupportedOperationException();
+  }
+
+  public PersistenceContext getPersistenceContext() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int executeUpdate(String query, QueryParameters queryParameters)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int executeNativeUpdate(NativeSQLQuerySpecification specification,
+      QueryParameters queryParameters) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityMode getEntityMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public CacheMode getCacheMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setCacheMode(CacheMode cm) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isOpen() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isConnected() {
+    throw new UnsupportedOperationException();
+  }
+
+  public FlushMode getFlushMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setFlushMode(FlushMode fm) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection connection() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void flush() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getNamedQuery(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getNamedSQLQuery(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isEventSource() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void afterScrollOperation() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setFetchProfile(String name) {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getFetchProfile() {
+    throw new UnsupportedOperationException();
+  }
+
+  public JDBCContext getJDBCContext() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isClosed() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/TypeDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/TypeDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/defaultmock/TypeDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,223 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.defaultmock;
+
+import org.hibernate.type.Type;
+import org.hibernate.type.ForeignKeyDirection;
+import org.hibernate.engine.Mapping;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.MappingException;
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.dom4j.Node;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class TypeDefaultMock implements Type {
+
+  public boolean isAssociationType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isCollectionType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isComponentType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isEntityType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isAnyType() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isXMLElement() {
+    throw new UnsupportedOperationException();
+  }
+
+  public int[] sqlTypes(Mapping mapping) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getColumnSpan(Mapping mapping) throws MappingException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Class getReturnedClass() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isSame(Object x, Object y, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isEqual(Object x, Object y, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isEqual(Object x, Object y, EntityMode entityMode,
+      SessionFactoryImplementor factory) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getHashCode(Object x, EntityMode entityMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int getHashCode(Object x, EntityMode entityMode,
+      SessionFactoryImplementor factory) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int compare(Object x, Object y, EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isDirty(Object old, Object current, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isDirty(Object old, Object current, boolean[] checkable,
+      SessionImplementor session) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isModified(Object oldHydratedState, Object currentState,
+      boolean[] checkable, SessionImplementor session)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object nullSafeGet(ResultSet rs, String[] names,
+      SessionImplementor session, Object owner)
+      throws HibernateException, SQLException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object nullSafeGet(ResultSet rs, String name,
+      SessionImplementor session, Object owner)
+      throws HibernateException, SQLException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void nullSafeSet(PreparedStatement st, Object value, int index,
+      boolean[] settable, SessionImplementor session)
+      throws HibernateException, SQLException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void nullSafeSet(PreparedStatement st, Object value, int index,
+      SessionImplementor session) throws HibernateException, SQLException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setToXMLNode(Node node, Object value,
+      SessionFactoryImplementor factory) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String toLoggableString(Object value,
+      SessionFactoryImplementor factory) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object fromXMLNode(Node xml, Mapping factory)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object deepCopy(Object value, EntityMode entityMode,
+      SessionFactoryImplementor factory) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isMutable() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable disassemble(Object value, SessionImplementor session,
+      Object owner) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object assemble(Serializable cached, SessionImplementor session,
+      Object owner) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void beforeAssemble(Serializable cached, SessionImplementor session) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object hydrate(ResultSet rs, String[] names,
+      SessionImplementor session, Object owner)
+      throws HibernateException, SQLException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object resolve(Object value, SessionImplementor session, Object owner)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object semiResolve(Object value, SessionImplementor session,
+      Object owner) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type getSemiResolvedType(SessionFactoryImplementor factory) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object replace(Object original, Object target,
+      SessionImplementor session, Object owner, Map copyCache)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object replace(Object original, Object target,
+      SessionImplementor session, Object owner, Map copyCache,
+      ForeignKeyDirection foreignKeyDirection) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean[] toColumnNullness(Object value, Mapping mapping) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/engine/ShardedSessionImplementorDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/engine/ShardedSessionImplementorDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/engine/ShardedSessionImplementorDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,448 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.engine;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardId;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.EntityMode;
+import org.hibernate.FlushMode;
+import org.hibernate.CacheMode;
+import org.hibernate.SessionFactory;
+import org.hibernate.LockMode;
+import org.hibernate.ReplicationMode;
+import org.hibernate.Transaction;
+import org.hibernate.Criteria;
+import org.hibernate.SQLQuery;
+import org.hibernate.Filter;
+import org.hibernate.classic.Session;
+import org.hibernate.stat.SessionStatistics;
+import org.hibernate.type.Type;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collection;
+import java.io.Serializable;
+import java.sql.Connection;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedSessionImplementorDefaultMock implements ShardedSessionImplementor {
+
+  public List<Shard> getShards() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object saveOrUpdateCopy(String entityName, Object object,
+      Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List find(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter, Object value,
+      Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Collection filter(Object collection, String filter, Object[] values,
+      Type[] types) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query, Object value, Type type)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int delete(String query, Object[] values, Type[] types)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createSQLQuery(String sql, String returnAlias,
+      Class returnClass) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createSQLQuery(String sql, String[] returnAliases,
+      Class[] returnClasses) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void save(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void save(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(String entityName, Object object, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public EntityMode getEntityMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session getSession(EntityMode entityMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void flush() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public FlushMode getFlushMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public CacheMode getCacheMode() {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionFactory getSessionFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection connection() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection close() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void cancelQuery() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isOpen() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isConnected() {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean isDirty() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getIdentifier(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean contains(Object object) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void evict(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(Class theClass, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(String entityName, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(Class theClass, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object load(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void load(Object object, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicate(Object object, ReplicationMode replicationMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void replicate(String entityName, Object object,
+      ReplicationMode replicationMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable save(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void saveOrUpdate(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void update(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object merge(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object merge(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void persist(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void persist(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void delete(String entityName, Object object)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lock(Object object, LockMode lockMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lock(String entityName, Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void refresh(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void refresh(Object object, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public LockMode getCurrentLockMode(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Transaction beginTransaction() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Transaction getTransaction() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(Class persistentClass) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(Class persistentClass, String alias) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String entityName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Criteria createCriteria(String entityName, String alias) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createQuery(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public SQLQuery createSQLQuery(String queryString) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query createFilter(Object collection, String queryString)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query getNamedQuery(String queryName) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class clazz, Serializable id) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(Class clazz, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object get(String entityName, Serializable id, LockMode lockMode)
+      throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getEntityName(Object object) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Filter enableFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Filter getEnabledFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void disableFilter(String filterName) {
+    throw new UnsupportedOperationException();
+  }
+
+  public SessionStatistics getStatistics() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void setReadOnly(Object entity, boolean readOnly) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Connection disconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void reconnect() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public void reconnect(Connection connection) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Session getSessionForObject(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardId getShardIdForObject(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+
+  public void lockShard() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedTableHiLoGeneratorTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedTableHiLoGeneratorTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedTableHiLoGeneratorTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,275 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+import org.hibernate.shards.defaultmock.SessionImplementorDefaultMock;
+import org.hibernate.shards.session.ControlSessionProvider;
+
+import junit.framework.TestCase;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.Query;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Transaction;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.engine.EntityKey;
+import org.hibernate.engine.PersistenceContext;
+import org.hibernate.engine.QueryParameters;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
+import org.hibernate.event.EventListeners;
+import org.hibernate.impl.CriteriaImpl;
+import org.hibernate.jdbc.Batcher;
+import org.hibernate.jdbc.JDBCContext;
+import org.hibernate.loader.custom.CustomQuery;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.sql.Connection;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ShardedTableHiLoGeneratorTest extends TestCase {
+
+  public void testGenerate() {
+    final SessionImplementor controlSessionToReturn = new MySession();
+    ControlSessionProvider provider = new ControlSessionProvider() {
+      public SessionImplementor openControlSession() {
+        return controlSessionToReturn;
+      }
+    };
+    final SessionImplementor session = new SessionImplementorDefaultMock();
+    ShardedTableHiLoGenerator gen = new ShardedTableHiLoGenerator() {
+      @Override
+      Serializable superGenerate(SessionImplementor controlSession, Object obj) {
+        assertSame(controlSessionToReturn, controlSession);
+        return 33;
+      }
+    };
+    gen.setControlSessionProvider(provider);
+    assertEquals(33, gen.generate(session, null));
+  }
+
+  private static final class MySession extends SessionDefaultMock implements SessionImplementor {
+
+    @Override
+    public Connection close() throws HibernateException {
+      return null;
+    }
+
+    public Interceptor getInterceptor() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setAutoClear(boolean enabled) {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isTransactionInProgress() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void initializeCollection(PersistentCollection collection,
+        boolean writing) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object internalLoad(String entityName, Serializable id, boolean eager,
+        boolean nullable) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object immediateLoad(String entityName, Serializable id)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public long getTimestamp() {
+      throw new UnsupportedOperationException();
+    }
+
+    public SessionFactoryImplementor getFactory() {
+      throw new UnsupportedOperationException();
+    }
+
+    public Batcher getBatcher() {
+      throw new UnsupportedOperationException();
+    }
+
+    public List list(String query, QueryParameters queryParameters)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Iterator iterate(String query, QueryParameters queryParameters)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScrollableResults scroll(String query, QueryParameters queryParameters)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScrollableResults scroll(CriteriaImpl criteria,
+        ScrollMode scrollMode) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List list(CriteriaImpl criteria) {
+      throw new UnsupportedOperationException();
+    }
+
+    public List listFilter(Object collection, String filter,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Iterator iterateFilter(Object collection, String filter,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public EntityPersister getEntityPersister(String entityName, Object object)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object getEntityUsingInterceptor(EntityKey key)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public void afterTransactionCompletion(boolean successful, Transaction tx) {
+      throw new UnsupportedOperationException();
+    }
+
+    public void beforeTransactionCompletion(Transaction tx) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Serializable getContextEntityIdentifier(Object object) {
+      throw new UnsupportedOperationException();
+    }
+
+    public String bestGuessEntityName(Object object) {
+      throw new UnsupportedOperationException();
+    }
+
+    public String guessEntityName(Object entity) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object instantiate(String entityName, Serializable id)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public List listCustomQuery(CustomQuery customQuery,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScrollableResults scrollCustomQuery(CustomQuery customQuery,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public List list(NativeSQLQuerySpecification spec,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public ScrollableResults scroll(NativeSQLQuerySpecification spec,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Object getFilterParameterValue(String filterParameterName) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Type getFilterParameterType(String filterParameterName) {
+      throw new UnsupportedOperationException();
+    }
+
+    public Map getEnabledFilters() {
+      throw new UnsupportedOperationException();
+    }
+
+    public int getDontFlushFromFind() {
+      throw new UnsupportedOperationException();
+    }
+
+    public EventListeners getListeners() {
+      throw new UnsupportedOperationException();
+    }
+
+    public PersistenceContext getPersistenceContext() {
+      throw new UnsupportedOperationException();
+    }
+
+    public int executeUpdate(String query, QueryParameters queryParameters)
+        throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public int executeNativeUpdate(NativeSQLQuerySpecification specification,
+        QueryParameters queryParameters) throws HibernateException {
+      throw new UnsupportedOperationException();
+    }
+
+    public Query getNamedSQLQuery(String name) {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isEventSource() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void afterScrollOperation() {
+      throw new UnsupportedOperationException();
+    }
+
+    public void setFetchProfile(String name) {
+      throw new UnsupportedOperationException();
+    }
+
+    public String getFetchProfile() {
+      throw new UnsupportedOperationException();
+    }
+
+    public JDBCContext getJDBCContext() {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean isClosed() {
+      throw new UnsupportedOperationException();
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedUUIDGeneratorTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedUUIDGeneratorTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/ShardedUUIDGeneratorTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.session.ShardedSessionImpl;
+
+import junit.framework.TestCase;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedUUIDGeneratorTest extends TestCase {
+  private ShardedUUIDGenerator gen;
+
+  @Override
+  protected void setUp() {
+    gen = new ShardedUUIDGenerator();
+  }
+
+  public void testHexShardEncoding() throws Exception {
+    Properties prop = new Properties();
+    prop.setProperty("sharded-uuid-type", "STRING");
+    gen.configure(null, prop, null);
+    ShardedSessionImpl.setCurrentSubgraphShardId(new ShardId(13));
+    Serializable id = gen.generate(null, null);
+    assertEquals(new ShardId(13), gen.extractShardId(id));
+  }
+
+  public void testIntegerShardEncoding() throws Exception {
+    Properties prop = new Properties();
+    gen.configure(null, prop, null);
+    ShardedSessionImpl.setCurrentSubgraphShardId(new ShardId(13));
+    Serializable id = gen.generate(null, null);
+    assertEquals(new ShardId(13), gen.extractShardId(id));
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/UUIDBigIntGenerator.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/UUIDBigIntGenerator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/id/UUIDBigIntGenerator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.id;
+
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.id.UUIDHexGenerator;
+
+import java.math.BigInteger;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class UUIDBigIntGenerator extends UUIDHexGenerator {
+
+  @Override
+  public BigInteger generate(SessionImplementor session, Object obj) {
+    String str =
+        new StringBuilder(32).append(format((short)0))
+                                      .append(format(getIP()))
+                                      .append(format((short)(getJVM()>>>16)))
+                                      .append(format(getHiTime()))
+                                      .append(format(getLoTime()))
+                                      .append(format(getCount()))
+                                      .toString();
+    return new BigInteger(str, 16);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,359 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.ShardedConfiguration;
+import org.hibernate.shards.session.ShardedSessionFactory;
+import org.hibernate.shards.integration.platform.DatabasePlatform;
+import org.hibernate.shards.integration.platform.DatabasePlatformFactory;
+import org.hibernate.shards.loadbalance.RoundRobinShardLoadBalancer;
+import org.hibernate.shards.session.ShardedSessionImpl;
+import org.hibernate.shards.session.ShardedSession;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyImpl;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.strategy.access.ParallelShardAccessStrategy;
+import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.resolution.AllShardsShardResolutionStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+import org.hibernate.shards.strategy.selection.RoundRobinShardSelectionStrategy;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.util.JdbcUtil;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base class for all sharding integration tests.
+ * Sets up and tears down in-memory hypersonic dbs.
+ * The rest is up to you.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public abstract class BaseShardingIntegrationTestCase extends TestCase implements HasPermutation {
+
+  private Permutation perm = Permutation.DEFAULT;
+
+  protected ShardedSessionFactory sf;
+  protected ShardedSession session;
+
+  public void setPermutation(Permutation perm) {
+    this.perm = perm;
+  }
+
+  /**
+   * Gosh, it sure seems expensive to be initializing a ThreadPoolExecutor
+   * for each test that needs it rather than initializing it once and just
+   * using it for any test that needs it.  So why do it this way?  Well, first
+   * read my novella in MemoryLeakPlugger.  Done?  Ok, welcome back.  So you
+   * should now recognize that the MemoryLeakPlugger is used to clear out the
+   * value of a specific, problematic ThreadLocal.  But what do you think happens
+   * if Hibernate and CGLib were doing their thing in some other thread?
+   * Exactly.  The MemoryLeakPlugger isn't going to be able to clear out the
+   * Callbacks that were initialized in different threads, and any test
+   * that does work in other threads is going to cause memory leaks.  The
+   * solution is to make sure the threads die (all ThreadLocals get gc'ed when
+   * a Thread dies), so we initialize and shutdown the ThreadPoolExecutor for
+   * every test that needs it.
+   */
+  protected ThreadPoolExecutor executor;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    for(int i = 0; i < getNumDatabases(); i++) {
+      destroyDatabase(i);
+      createDatabase(i);
+    }
+    List<Configuration> configurations = buildConfigurations();
+    // now we use these configs to build our sharded config
+    ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
+    Map<Integer, Integer> virtualShardMap = buildVirtualShardToShardMap();
+    // we base the configuration off of the shard0 config with the expectation
+    // that all other configs will be the same
+    ShardedConfiguration shardedConfig =
+        new ShardedConfiguration(
+            configurations.get(0),
+            configurations,
+            shardStrategyFactory,
+            virtualShardMap);
+    sf = shardedConfig.buildShardedSessionFactory();
+    session = openSession();
+  }
+
+  protected ShardedSession openSession() {
+    return sf.openSession();
+  }
+
+  protected Map<Integer, Integer> buildVirtualShardToShardMap() {
+    Map<Integer, Integer> virtualShardToShardMap = Maps.newHashMap();
+    if (isVirtualShardingEnabled()) {
+      for(int i = 0; i < getNumShards(); ++i) {
+        virtualShardToShardMap.put(Integer.valueOf(i), Integer.valueOf(i % getNumDatabases()));
+      }
+    }
+    return virtualShardToShardMap;
+  }
+
+  protected List<Configuration> buildConfigurations() {
+    DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+    String dbPlatformConfigDirectory = "platform/" + dbPlatform.getName().toLowerCase() +"/config/";
+    IdGenType idGenType = getIdGenType();
+    List<Configuration> configs = Lists.newArrayList();
+    for(int i = 0; i < getNumDatabases(); i++) {
+      Configuration config = new Configuration();
+      config.configure(BaseShardingIntegrationTestCase.class.getResource(dbPlatformConfigDirectory + "shard" + i + ".hibernate.cfg.xml"));
+      config.addURL(BaseShardingIntegrationTestCase.class.getResource(dbPlatformConfigDirectory + idGenType.getMappingFile()));
+      configs.add(config);
+    }
+    return configs;
+  }
+
+  protected ShardStrategyFactory buildShardStrategyFactory() {
+    return new ShardStrategyFactory() {
+      public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+        RoundRobinShardLoadBalancer loadBalancer = new RoundRobinShardLoadBalancer(shardIds);
+        ShardSelectionStrategy sss = new RoundRobinShardSelectionStrategy(loadBalancer);
+        ShardResolutionStrategy srs = new AllShardsShardResolutionStrategy(shardIds);
+        ShardAccessStrategy sas = getShardAccessStrategy();
+        return new ShardStrategyImpl(sss, srs, sas);
+      }
+    };
+  }
+
+  protected void resetSession() {
+    MemoryLeakPlugger.plug((ShardedSessionImpl)session);
+    session.close();
+    session = openSession();
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    if(executor != null) {
+      executor.shutdownNow();
+      executor = null;
+    }
+
+    try {
+      if(session != null) {
+        MemoryLeakPlugger.plug((ShardedSessionImpl)session);
+        session.close();
+        session = null;
+      }
+    } finally {
+      if(sf != null) {
+        sf.close();
+        sf = null;
+      }
+    }
+    ShardedSessionImpl.setCurrentSubgraphShardId(null);
+    super.tearDown();
+  }
+
+  public Connection createConnection(int index) throws SQLException {
+    DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+    return
+        DriverManager.getConnection(
+            dbPlatform.getUrl(index),
+            dbPlatform.getUser(),
+            dbPlatform.getPassword());
+  }
+
+  private void destroyDatabase(int index) throws SQLException {
+    DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+    Connection conn = createConnection(index);
+    try {
+      for(String statement : dbPlatform.getDropTableStatements(getIdGenType())) {
+        try {
+          JdbcUtil.executeUpdate(conn, statement, false);
+        } catch (SQLException sqle) {
+          // not interested, keep moving
+        }
+      }
+    } finally {
+      conn.close();
+    }
+  }
+
+  private void createDatabase(int index) throws SQLException {
+    DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+    Connection conn = createConnection(index);
+    try {
+      for(String statement : dbPlatform.getCreateTableStatements(getIdGenType())) {
+        JdbcUtil.executeUpdate(conn, statement, false);
+      }
+      createDatabaseHook(conn);
+    } finally {
+      conn.close();
+    }
+  }
+
+  /**
+   * Override if you want additional tables in your schema
+   */
+  protected void createDatabaseHook(Connection conn) {
+  }
+
+  /**
+   * Override if you want more than the default
+   */
+  protected int getNumDatabases() {
+    return perm.getNumDbs();
+  }
+
+  protected int getNumShards() {
+    if (isVirtualShardingEnabled()) {
+      return perm.getNumShards();
+    }
+    return getNumDatabases();
+  }
+
+  protected boolean isVirtualShardingEnabled() {
+    return perm.isVirtualShardingEnabled();
+  }
+
+  protected IdGenType getIdGenType() {
+    return perm.getIdGenType();
+  }
+
+  protected ShardAccessStrategyType getShardAccessStrategyType() {
+    return perm.getSast();
+  }
+
+  protected <T> T reloadAssertNotNull(T reloadMe) {
+    T result = reload(reloadMe);
+    assertNotNull(result);
+    return result;
+  }
+
+  protected <T> T reload(T reloadMe) {
+    return reload(session, reloadMe);
+  }
+
+  protected <T> T reloadAssertNotNull(Session session, T reloadMe) {
+    T result = (T) reloadAll(session, reloadMe)[0];
+    assertNotNull(result);
+    return result;
+  }
+
+  protected <T> T reload(Session session, T reloadMe) {
+    return (T) reloadAll(session, reloadMe)[0];
+  }
+
+  protected Object[] reloadAll(Session session, Object... reloadMe) {
+    List<Object> retVal = Lists.newArrayList();
+    for(Object obj : reloadMe) {
+      Class clazz = obj.getClass();
+      String className = clazz.getSimpleName();
+      try {
+        Method m = clazz.getMethod("get" + className + "Id");
+        retVal.add(session.get(clazz, (Serializable) m.invoke(obj)));
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      } catch (InvocationTargetException e) {
+        throw new RuntimeException(e);
+      }
+    }
+    return retVal.toArray();
+  }
+
+  protected ShardId getShardIdForObject(Object obj) {
+    return session.getShardIdForObject(obj);
+  }
+
+  private ShardAccessStrategy getShardAccessStrategy() {
+    switch(getShardAccessStrategyType()) {
+      case SEQUENTIAL:
+        return new SequentialShardAccessStrategy();
+      case PARALLEL:
+        executor = buildThreadPoolExecutor();
+        return new ParallelShardAccessStrategy(executor);
+      default:
+        throw new RuntimeException("unsupported shard access strategy type");
+    }
+  }
+
+  private static final ThreadFactory FACTORY = new ThreadFactory() {
+    private int nextThreadId = 0;
+    public Thread newThread(Runnable r) {
+      Thread t = Executors.defaultThreadFactory().newThread(r);
+      t.setDaemon(true);
+      t.setName("T" + (nextThreadId++));
+      return t;
+    }
+  };
+
+  private ThreadPoolExecutor buildThreadPoolExecutor() {
+    return new ThreadPoolExecutor(10, 50, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), FACTORY);
+  }
+
+  /**
+   * Catch all throwables so we get an opportunity to add info about the
+   * permutation under which the failure took place. 
+   */
+  @Override
+  public void runBare() throws Throwable {
+    try {
+      super.runBare();
+    } catch (AssertionFailedError afe) {
+      AssertionFailedError newError = new AssertionFailedError(perm.getMessageWithPermutationPrefix(afe.getMessage()));
+      newError.setStackTrace(afe.getStackTrace());
+      throw newError;
+    } catch (Throwable t) {
+      throw new ThrowableDecorator(t);
+    }
+  }
+
+  private final class ThrowableDecorator extends Throwable {
+
+    public ThrowableDecorator(Throwable t) {
+      super(t);
+    }
+
+    @Override
+    public String getMessage() {
+      return perm.getMessageWithPermutationPrefix(getCause().getMessage());
+    }
+  }
+}
+
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCasePermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCasePermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCasePermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+/**
+ * This test only exists to test the db setup/teardown functionality in the
+ * base class.  Since we have multiple tests, a successful run here proves
+ * that the teardown actually removes the in memory db.  If it didn't,
+ * the setup for the second test would fail because the tables would already
+ * exist.
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class BaseShardingIntegrationTestCasePermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  public void testThatThing() {
+  }
+
+  public void testThatOtherThing() {
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ConfigPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ConfigPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ConfigPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+import org.hibernate.shards.session.ShardedSessionImpl;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ConfigPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  public void testShardedEnvironment() {
+    assertTrue(((ShardedSessionImpl)session).getCheckAllAssociatedObjectsForDifferentShards());
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
+import org.hibernate.shards.util.JdbcStrategy;
+import org.hibernate.shards.util.JdbcUtil;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Set;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class DbAccessPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  public void testAccess() throws SQLException {
+    Set<? extends SessionFactory> sfSet = ((ShardedSessionFactoryImplementor)sf).getSessionFactoryShardIdMap().keySet();
+    for(SessionFactory sf : sfSet) {
+      testShard(sf);
+      testShard(sf);
+      testShard(sf);
+    }
+  }
+
+  private void testShard(SessionFactory sf) throws SQLException {
+    Session session = sf.openSession();
+    try {
+      Connection conn = session.connection();
+      insertRecord(conn);
+      updateRecord(conn);
+      selectRecord(conn);
+      deleteRecord(conn);
+    } finally {
+      session.close();
+    }
+  }
+
+  private void insertRecord(Connection conn) throws SQLException {
+    assertEquals(1, JdbcUtil.executeUpdate(conn, "INSERT INTO sample_table(id, str_col) values (0, 'yam')", false));
+  }
+
+  private void updateRecord(Connection conn) throws SQLException {
+    assertEquals(1, JdbcUtil.executeUpdate(conn, "UPDATE sample_table set str_col = 'max' where id = 0", false));
+  }
+
+  private void selectRecord(Connection conn) throws SQLException {
+    JdbcStrategy strat = new JdbcStrategy() {
+      public void extractData(ResultSet rs) throws SQLException {
+        assertEquals(0, rs.getInt("id"));
+        assertEquals("max", rs.getString("str_col"));
+        assertFalse(rs.next());
+      }
+    };
+    JdbcUtil.executeJdbcQuery(conn, "select id, str_col from sample_table where id = 0", strat, false);
+  }
+
+  private void deleteRecord(Connection conn) throws SQLException {
+    assertEquals(1, JdbcUtil.executeUpdate(conn, "DELETE from sample_table where id = 0", false));
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/HasPermutation.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/HasPermutation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/HasPermutation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public interface HasPermutation {
+  void setPermutation(Permutation perm);
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/IdGenType.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/IdGenType.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/IdGenType.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public enum IdGenType {
+  SIMPLE("mappings.hbm.xml", false),
+  SHARD_HI_LO("mappings-shardedTableHiLo.hbm.xml", false),
+  SHARD_UUID("mappings-shardedUUID.hbm.xml", true);
+
+  private final String mappingFile;
+  private final boolean supportsVirtualSharding;
+
+  private IdGenType(String mappingFile, boolean supportsVirtualSharding) {
+   this.mappingFile = mappingFile;
+   this.supportsVirtualSharding = supportsVirtualSharding;
+ }
+
+  public String getMappingFile() {
+    return mappingFile;
+  }
+
+  public boolean getSupportsVirtualSharding() {
+    return supportsVirtualSharding;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/MemoryLeakPlugger.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/MemoryLeakPlugger.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/MemoryLeakPlugger.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,131 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.session.ShardedSessionImpl;
+
+import net.sf.cglib.proxy.Callback;
+
+import org.hibernate.engine.StatefulPersistenceContext;
+import org.hibernate.impl.SessionImpl;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * Summary of what I've learned.
+ *
+ * When Hibernate reads an object from the db that has a singular association
+ * (one-to-one or the one side of a one-to-many) and the fetch policy for
+ * that association is lazy, a proxy for that object is created using cglib.
+ * When the proxy is created, an array of Callback objects is set in a
+ * ThreadLocal member of the proxy.  One of the Callback objects is typically
+ * a CGLibLazyInitializer.  The CGLibLazyInitializer maintains a reference to
+ * the current session, which maintains a reference to our
+ * CrossShardRelationshipDetectingInterceptor, which maintains a reference to
+ * our ShardedSessionImpl, which maintains a relationship to our
+ * ShardedSessionFactoryImpl.  The point here is that unless that ThreadLocal
+ * gets removed, our ShardedSessionFactoryImp (and all the crap that hangs off
+ * of it) is never going to get garbage collected.  When you have a unit test
+ * framework that initializes a fresh ShardedSessionFactoryImpl for every test,
+ * that's a problem.
+ *
+ * The solution implemented herein is use reflection to go in and clear out
+ * the ThreadLocal before the session gets closed.  The code to do this is of
+ * course hairy and unreadable because we're dealing with classes that were
+ * generated on the fly, so we can only do it via reflection.
+ *
+ * @author maxr at google.com (Max Ross)
+ */
+public class MemoryLeakPlugger {
+
+  static final Callback[] NO_CALLBACKS = new Callback[0];
+
+  static final Object[] ONE_CALLBACK_ARRAY = {NO_CALLBACKS};
+
+  static final Class[] SET_THREAD_CALLBACKS_ARGS = {Callback[].class};
+  static final Class[] GET_THREAD_CALLBACKS_ARGS = {};
+
+  private static final Field PROXIES_BY_KEY_FIELD;
+  static {
+    try {
+      PROXIES_BY_KEY_FIELD = StatefulPersistenceContext.class.getDeclaredField("proxiesByKey");
+    } catch (NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+
+  private MemoryLeakPlugger() {}
+
+  public static void plug(ShardedSessionImpl ssi) {
+    for(Shard shard : ssi.getShards()) {
+      if(shard.getSession() != null) {
+        plug((SessionImpl)shard.getSession());
+      }
+    }
+  }
+
+  public static void plug(final SessionImpl session) {
+    try {
+      /**
+       * Get proxy from the PersistenceContext.  This is a private field
+       * without an accessor so we're just going to have to use reflection
+       * to get ahold of it.  Desperate times and all that.
+       */
+      Map map = accessibleCall(PROXIES_BY_KEY_FIELD, new Callable<Map>() {
+        public Map call() throws Exception {
+          return (Map) PROXIES_BY_KEY_FIELD.get(session.getPersistenceContext());
+        }
+      });
+
+      /**
+       * Every value in this map should be an instance of a cglib-generated
+       * class.
+       */
+      for(final Object obj : map.values()) {
+        // get ahold of the method that we can use to set the callbacks
+        Method setThreadCallbacks = obj.getClass().getDeclaredMethod("CGLIB$SET_THREAD_CALLBACKS", SET_THREAD_CALLBACKS_ARGS);
+        // call the method, passing an array with 0 Callbacks
+        setThreadCallbacks.invoke(null, ONE_CALLBACK_ARRAY);
+      }
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Helper function that makes the given object accessible, invokes the Callable,
+   * and then sets the accessibility of the object back to its original value.
+   */
+  private static <T> T accessibleCall(AccessibleObject obj, Callable<T> callable)
+      throws Exception {
+    boolean isAccessible = obj.isAccessible();
+    obj.setAccessible(true);
+    try {
+      return callable.call();
+    } finally {
+      obj.setAccessible(isAccessible);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/Permutation.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/Permutation.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/Permutation.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,113 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+final class Permutation {
+
+  static final Permutation DEFAULT = new Permutation(IdGenType.SIMPLE, ShardAccessStrategyType.SEQUENTIAL, 3, 3, false);
+
+  private final IdGenType idGenType;
+  private final ShardAccessStrategyType sast;
+  private final int numDbs;
+  private final int numShards;
+  private final boolean virtualShardingEnabled;
+
+  public Permutation(IdGenType idGenType, ShardAccessStrategyType sast,
+      int numDbs) {
+    this(idGenType, sast, numDbs, numDbs, false);
+  }
+
+  public Permutation(IdGenType idGenType, ShardAccessStrategyType sast,
+      int numDbs, int numShards, boolean virtualShardingEnabled) {
+    this.idGenType = idGenType;
+    this.sast = sast;
+    this.numDbs = numDbs;
+    this.numShards = numShards;
+    this.virtualShardingEnabled = virtualShardingEnabled;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Permutation that = (Permutation) o;
+
+    if (numDbs != that.numDbs) {
+      return false;
+    }
+    if (numShards != that.numShards) {
+      return false;
+    }
+    if (idGenType != that.idGenType) {
+      return false;
+    }
+    if (virtualShardingEnabled != that.virtualShardingEnabled) {
+      return false;
+    }
+    return sast == that.sast;
+  }
+
+  @Override
+  public int hashCode() {
+    int result;
+    result = idGenType.hashCode();
+    result = 29 * result + sast.hashCode();
+    result = 29 * result + numDbs;
+    result = 29 * result + numShards;
+    result = 29 * result + (virtualShardingEnabled ? 1 : 0);
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return idGenType.name() + " - " + sast.name() + " - " + numDbs + (virtualShardingEnabled ? " - " + numShards + " VIRTUAL SHARDS" : "");
+  }
+
+  public IdGenType getIdGenType() {
+    return idGenType;
+  }
+
+  public ShardAccessStrategyType getSast() {
+    return sast;
+  }
+
+  public int getNumDbs() {
+    return numDbs;
+  }
+
+  public int getNumShards() {
+    return numShards;
+  }
+
+  public boolean isVirtualShardingEnabled() {
+    return virtualShardingEnabled;
+  }
+
+  public String getMessageWithPermutationPrefix(String msg) {
+    return toString() + ": " + msg;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/PermutedIntegrationTests.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/PermutedIntegrationTests.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/PermutedIntegrationTests.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,136 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+import org.hibernate.shards.integration.id.IdGeneratorPermutedIntegrationTest;
+import org.hibernate.shards.integration.model.InterceptorBehaviorPermutedIntegrationTest;
+import org.hibernate.shards.integration.model.ModelCriteriaPermutedIntegrationTest;
+import org.hibernate.shards.integration.model.ModelPermutedIntegrationTest;
+import org.hibernate.shards.integration.model.ModelQueryPermutedIntegrationTest;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class PermutedIntegrationTests extends TestSuite {
+
+  public static final List<Class<? extends TestCase>> CLASSES = Collections.unmodifiableList(buildListOfPermutedClasses());
+
+  private static List<Class<? extends TestCase>> buildListOfPermutedClasses() {
+    List<Class<? extends TestCase>> classes = new ArrayList<Class<? extends TestCase>>();
+    classes.add(BaseShardingIntegrationTestCasePermutedIntegrationTest.class);
+    classes.add(IdGeneratorPermutedIntegrationTest.class);
+    classes.add(ModelPermutedIntegrationTest.class);
+    classes.add(InterceptorBehaviorPermutedIntegrationTest.class);
+    classes.add(ModelCriteriaPermutedIntegrationTest.class);
+    classes.add(ModelQueryPermutedIntegrationTest.class);
+    classes.add(ConfigPermutedIntegrationTest.class);
+    classes.add(DbAccessPermutedIntegrationTest.class);
+    return classes;
+  }
+
+  public static Test suite() {
+    TestSuite suiteOfTestsNeedingPermutation = buildSuiteOfTestsNeedingPermutation();
+    TestSuite permutedSuite = new TestSuite("Permuted Integration Tests");
+    /**
+     * Build a separate test suite for each permutation.  We are permuting
+     * along type of id generation, shard access strategy, and number of shards
+     */
+    for(Permutation perm : buildPermutationList()) {
+      TestSuite permutationSuite = new TestSuite(perm.toString());
+      permutedSuite.addTest(permutationSuite);
+      addPermutations(suiteOfTestsNeedingPermutation, perm, permutationSuite);
+    }
+    return permutedSuite;
+  }
+
+  private static TestSuite buildSuiteOfTestsNeedingPermutation() {
+    TestSuite suite = new TestSuite();
+    for(Class<? extends TestCase> testClass : CLASSES) {
+      suite.addTestSuite(testClass);
+    }
+    return suite;
+  }
+
+  private static final int MIN_SHARDS = 1;
+  private static final int MAX_SHARDS = 3;
+
+  private static List<Permutation> buildPermutationList() {
+    List<Permutation> list = Lists.newArrayList();
+    for(IdGenType idGenType : IdGenType.values()) {
+      for(ShardAccessStrategyType sast : ShardAccessStrategyType.values()) {
+        for(int i = MIN_SHARDS; i <= MAX_SHARDS; i++) {
+          list.add(new Permutation(idGenType, sast, i));
+          if (idGenType.getSupportsVirtualSharding()) {
+            list.add(new Permutation(idGenType, sast, i, 9, true));
+            list.add(new Permutation(idGenType, sast, i, i, true));
+          }
+        }
+      }
+    }
+    return list;
+  }
+
+  private static void addPermutations(Test t, Permutation perm, TestSuite permutationSuite) {
+    if(t instanceof TestCase) {
+      addActualPermutation((TestCase)t, perm, permutationSuite);
+    } else if (t instanceof TestSuite) {
+      TestSuite ts = (TestSuite) t;
+      TestSuite subSuite = new TestSuite(ts.getName());
+      permutationSuite.addTest(subSuite);
+      for(Test test : asIterable(ts)) {
+        addPermutations(test, perm, subSuite);
+      }
+    } else {
+      throw new RuntimeException("wuzzat?");
+    }
+  }
+
+  private static void addActualPermutation(
+      TestCase testCase,
+      Permutation perm,
+      TestSuite permutationSuite) {
+      permutationSuite.addTest(createTest(testCase, perm));
+  }
+
+  private static Test createTest(
+      TestCase prototype,
+      Permutation permutation) {
+    Test t = TestSuite.createTest(prototype.getClass(), prototype.getName());
+    ((HasPermutation)t).setPermutation(permutation);
+    return t;
+  }
+
+  private static Iterable<Test> asIterable(TestSuite ts) {
+    List<Test> list = new ArrayList<Test>();
+    for(Enumeration testEnum = ts.tests(); testEnum.hasMoreElements(); ) {
+      list.add((Test) testEnum.nextElement());
+    }
+    return list;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ShardAccessStrategyType.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ShardAccessStrategyType.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/ShardAccessStrategyType.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public enum ShardAccessStrategyType {
+  SEQUENTIAL, PARALLEL
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/id/IdGeneratorPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/id/IdGeneratorPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/id/IdGeneratorPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,67 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.id;
+
+
+import org.hibernate.shards.integration.BaseShardingIntegrationTestCase;
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.util.Lists;
+
+
+import java.util.List;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class IdGeneratorPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  public void testSingleShard() {
+    session.beginTransaction();
+    Building b = new Building();
+    b.setName("foo");
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    assertNotNull(b.getBuildingId());
+
+    Building b2 = (Building)session.get(Building.class, b.getBuildingId());
+    assertNotNull(b2);
+    assertEquals(b.getName(), b2.getName());
+  }
+
+  public void testMultipleShards() {
+    session.beginTransaction();
+    List<Building> buildings = Lists.newArrayList();
+    for(int i = 0; i < getNumDatabases(); ++i) {
+      Building b = new Building();
+      b.setName("foo" + i);
+      buildings.add(b);
+      session.save(b);
+    }
+    session.getTransaction().commit();
+    resetSession();
+    for(Building b : buildings) {
+      assertNotNull(b.getBuildingId());
+      Building returnedBuilding = (Building)session.get(Building.class,  b.getBuildingId());
+      assertEquals(b.getName(), returnedBuilding.getName());
+    }
+  }
+
+}
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/InterceptorBehaviorPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/InterceptorBehaviorPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/InterceptorBehaviorPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,151 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+import org.hibernate.shards.integration.BaseShardingIntegrationTestCase;
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.session.BaseStatefulInterceptorFactory;
+import org.hibernate.shards.session.ShardedSession;
+import org.hibernate.shards.session.RequiresSession;
+import org.hibernate.shards.util.Lists;
+
+import org.hibernate.CallbackException;
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.Interceptor;
+import org.hibernate.TransactionException;
+import org.hibernate.Session;
+import org.hibernate.impl.SessionImpl;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class InterceptorBehaviorPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  private Interceptor interceptor;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    interceptor = new ExplosiveUpdateInterceptor();
+  }
+
+  @Override
+  protected ShardedSession openSession() {
+    return sf.openSession(interceptor);
+  }
+
+  public void testInterceptorBehaviorOnCommit() {
+    session.beginTransaction();
+    Building b = ModelDataFactory.building("b");
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    b.setName("updated b");
+    try {
+      session.getTransaction().commit();
+      fail("expected TransactionException");
+    } catch (TransactionException te) {
+      // good
+    }
+    resetSession();
+    b = reload(b);
+    assertEquals("b", b.getName());
+  }
+
+  public void testInterceptorBehaviorOnFlush() {
+    session.beginTransaction();
+    Building b = ModelDataFactory.building("b");
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    b.setName("updated b");
+    try {
+      session.flush();
+      fail("expected CallbackException");
+    } catch (CallbackException ce) {
+      // good
+    }
+    resetSession();
+    b = reload(b);
+    assertEquals("b", b.getName());
+  }
+
+  public void testStatefulInterceptorBehavior() {
+    final int[] calls = {0};
+    interceptor = new BaseStatefulInterceptorFactory() {
+      public Interceptor newInstance() {
+        calls[0]++;
+        return new ExplosiveUpdateInterceptor();
+      }
+    };
+    resetSession();
+
+    // this is how we know we were getting different interceptors
+    // for each shard
+    assertEquals(getNumDatabases(), calls[0]);
+  }
+
+  public void testStatefulInterceptorWithRequiresSessionBehavior() {
+    final List<Interceptor> interceptors = Lists.newArrayList();
+    class MyInterceptor extends EmptyInterceptor implements RequiresSession {
+      private boolean[] wasCalled = {false};
+      public void setSession(Session session) {
+        assertTrue(session instanceof SessionImpl);
+        wasCalled[0] = true;
+      }
+    }
+
+    final int[] calls = {0};
+    interceptor = new BaseStatefulInterceptorFactory() {
+      public Interceptor newInstance() {
+        calls[0]++;
+        Interceptor interceptor = new MyInterceptor();
+        interceptors.add(interceptor);
+        return interceptor;
+      }
+    };
+    resetSession();
+    session.createCriteria(Building.class).list(); // force the session to init
+    // this is how we know we were getting different interceptors
+    // for each shard
+    assertEquals(getNumDatabases(), calls[0]);
+    for(Interceptor interceptor : interceptors) {
+      assertTrue(((MyInterceptor)interceptor).wasCalled[0]);
+    }
+
+  }
+
+  private static final class ExplosiveUpdateInterceptor extends EmptyInterceptor {
+
+    @Override
+    public boolean onFlushDirty(Object entity, Serializable id,
+        Object[] currentState, Object[] previousState, String[] propertyNames,
+        Type[] types) {
+      throw new CallbackException("boom");
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/MemoryLeakTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/MemoryLeakTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/MemoryLeakTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,145 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+import org.hibernate.shards.integration.IdGenType;
+import org.hibernate.shards.integration.MemoryLeakPlugger;
+import static org.hibernate.shards.integration.model.ModelDataFactory.person;
+import static org.hibernate.shards.integration.model.ModelDataFactory.tenant;
+import org.hibernate.shards.integration.platform.DatabasePlatform;
+import org.hibernate.shards.integration.platform.DatabasePlatformFactory;
+import org.hibernate.shards.model.Person;
+import org.hibernate.shards.model.Tenant;
+import org.hibernate.shards.util.JdbcUtil;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.engine.StatefulPersistenceContext;
+import org.hibernate.impl.SessionImpl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Map;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class MemoryLeakTest extends TestCase {
+
+  private SessionFactory sf;
+  private Session session;
+
+  private Connection getConnection(DatabasePlatform dbPlatform) throws
+      SQLException {
+    return
+      DriverManager.getConnection(
+          dbPlatform.getUrl(0),
+          dbPlatform.getUser(),
+          dbPlatform.getPassword());
+  }
+
+  private void deleteDatabase(DatabasePlatform dbPlatform) throws SQLException {
+    Connection conn = getConnection(dbPlatform);
+    try {
+      for(String statement : dbPlatform.getDropTableStatements(IdGenType.SIMPLE)) {
+        try {
+          JdbcUtil.executeUpdate(conn, statement, false);
+        } catch (SQLException sqle) {
+          // not interested, keep moving
+        }
+      }
+    } finally {
+      conn.close();
+    }
+  }
+
+  private void createDatabase(DatabasePlatform dbPlatform) throws SQLException {
+    Connection conn = getConnection(dbPlatform);
+    try {
+      for(String statement : dbPlatform.getCreateTableStatements(IdGenType.SIMPLE)) {
+        JdbcUtil.executeUpdate(conn, statement, false);
+      }
+    } finally {
+      conn.close();
+    }
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+    deleteDatabase(dbPlatform);
+    createDatabase(dbPlatform);
+
+    String dbPlatformConfigDirectory = "../platform/" + dbPlatform.getName().toLowerCase() + "/" + "config/";
+    Configuration configuration = new Configuration();
+    configuration.configure(getClass().getResource(dbPlatformConfigDirectory + "shard0.hibernate.cfg.xml"));
+    configuration.addURL(getClass().getResource(dbPlatformConfigDirectory + IdGenType.SIMPLE.getMappingFile()));
+
+    sf = configuration.buildSessionFactory();
+    session = sf.openSession();
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    try {
+      MemoryLeakPlugger.plug((SessionImpl)session);
+      session.close();
+    } finally {
+      sf.close();
+    }
+    super.tearDown();
+  }
+
+  public void testLeak() throws SQLException, ClassNotFoundException,
+      NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
+      InvocationTargetException {
+    Person p;
+    try {
+      session.beginTransaction();
+      p = person("max", null);
+      Tenant t = tenant("tenant", null, Lists.newArrayList(p));
+      session.save(t);
+      session.getTransaction().commit();
+    } finally {
+      session.close();
+    }
+    session = sf.openSession();
+    session.get(Person.class, p.getPersonId());
+    Field f = StatefulPersistenceContext.class.getDeclaredField("proxiesByKey");
+    boolean isAccessible = f.isAccessible();
+    f.setAccessible(true);
+    try {
+      SessionImpl sessionImpl = (SessionImpl)session;
+      Map map = (Map) f.get(sessionImpl.getPersistenceContext());
+      assertEquals(1, map.size());
+    } finally {
+      f.setAccessible(isAccessible);
+    }
+
+    MemoryLeakPlugger.plug((SessionImpl)session);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,284 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+
+import org.hibernate.shards.integration.BaseShardingIntegrationTestCase;
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.model.Floor;
+import org.hibernate.shards.model.Office;
+import org.hibernate.shards.util.Lists;
+
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ModelCriteriaPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  private Building b1;
+  private Floor b1f1;
+  private Floor b1f2;
+  private Floor b1f3;
+  private Office b1f3o1;
+  private Office b1f3o2;
+
+  private Building b2;
+  private Floor b2f1;
+  private Office b2f1o1;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    session.beginTransaction();
+    b1 = ModelDataFactory.building("b1");
+    b1f1 = ModelDataFactory.floor(b1, 1);
+    b1f2 = ModelDataFactory.floor(b1, 2);
+    b1f3 = ModelDataFactory.floor(b1, 3);
+    b1f3o1 = ModelDataFactory.office("NOT LAHGE", b1f3);
+    b1f3o2 = ModelDataFactory.office("LAHGE", b1f3);
+    session.save(b1);
+    session.getTransaction().commit();
+
+    session.beginTransaction();
+    b2 = ModelDataFactory.building("b2");
+    b2f1 = ModelDataFactory.floor(b2, 1);
+    b2f1o1 = ModelDataFactory.office("LAHGE", b2f1);
+    session.save(b2);
+    session.getTransaction().commit();
+    resetSession();
+    b1 = reload(b1);
+    b1f1 = reload(b1f1);
+    b1f2 = reload(b1f2);
+    b1f3 = reload(b1f3);
+    b1f3o1 = reload(b1f3o1);
+    b1f3o2 = reload(b1f3o2);
+    b2 = reload(b2);
+    b2f1 = reload(b2f1);
+    b2f1o1 = reload(b2f1o1);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    b1 = null;
+    b1f1 = null;
+    b1f2 = null;
+    b1f3 = null;
+    b1f3o1 = null;
+    b1f3o2 = null;
+    b2 = null;
+    b2f1 = null;
+    b2f1o1 = null;
+    super.tearDown();
+  }
+
+  public void testLoadAllBuildings() {
+    Criteria crit = session.createCriteria(Building.class);
+    List<Building> buildings = list(crit);
+    assertEquals(2, buildings.size());
+    assertTrue(buildings.contains(b1));
+    assertTrue(buildings.contains(b2));
+  }
+
+  public void testLoadAllBuildingsAfterForcingEarlyInit() {
+    Criteria crit = session.createCriteria(Building.class);
+    // forces us to initialize an actual Criteria object
+    crit.getAlias();
+    List<Building> buildings = list(crit);
+    assertEquals(2, buildings.size());
+    assertTrue(buildings.contains(b1));
+    assertTrue(buildings.contains(b2));
+  }
+
+  public void testLoadBuildingByName() {
+    Criteria crit = session.createCriteria(Building.class);
+    crit.add(Restrictions.eq("name", "b2"));
+    Building b2Reloaded = uniqueResult(crit);
+    assertEquals(b2.getBuildingId(), b2Reloaded.getBuildingId());
+  }
+
+  public void testLoadBuildingByNameAfterForcingEarlyInit() {
+    Criteria crit = session.createCriteria(Building.class);
+    crit.add(Restrictions.eq("name", "b2"));
+    // forces us to initialize an actual Criteria object
+    crit.getAlias();
+    Building b2Reloaded = uniqueResult(crit);
+    assertEquals(b2.getBuildingId(), b2Reloaded.getBuildingId());
+  }
+
+  public void testLoadBuildingsByLikeName() {
+    Criteria crit = session.createCriteria(Building.class);
+    crit.add(Restrictions.in("name", Lists.newArrayList("b1", "b2")));
+    List<Building> buildings = list(crit);
+    assertEquals(2, buildings.size());
+    assertTrue(buildings.contains(b1));
+    assertTrue(buildings.contains(b2));
+  }
+
+  public void testLoadHighFloors() {
+    Criteria crit = session.createCriteria(Floor.class);
+    crit.add(Restrictions.ge("number", 3));
+    List<Floor> floors = list(crit);
+    assertEquals(1, floors.size());
+    assertTrue(floors.contains(b1f3));
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaTopLevelCriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    List<Building> l = list(crit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaTopLevelCriteriaAfterForcingEarlyInitOnTopLevelCriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    // forces us to initialize an actual Criteria object
+    crit.getAlias();
+    List<Building> l = list(crit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaTopLevelCriteriaAfterForcingEarlyInitOnSubcriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    // forces us to initialize an actual Criteria object
+    floorCrit.getAlias();
+    List<Building> l = list(crit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaSubcriteriaAfterForcingEarlyInitOnSubcriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    // forces us to initialize an actual Criteria object
+    floorCrit.getAlias();
+    List<Building> l = list(floorCrit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaSubcriteriaAfterForcingEarlyInitOnTopLevelCriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    // forces us to initialize an actual Criteria object
+    crit.getAlias();
+    List<Building> l = list(floorCrit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsViaSubcriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    floorCrit.add(Restrictions.ge("number", 3));
+    // note how we execute the query via the floorCrit
+    List<Building> l = list(floorCrit);
+    assertEquals(1, l.size());
+  }
+
+  public void testLoadBuildingsWithLargeOfficesViaTopLevelCriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    Criteria officeCrit = floorCrit.createCriteria("offices");
+    officeCrit.add(Restrictions.eq("label", "LAHGE"));
+    List<Building> l = list(crit);
+    assertEquals(2, l.size());
+  }
+
+  public void testLoadBuildingsWithLargeOfficesViaSubcriteria() {
+    Criteria crit = session.createCriteria(Building.class);
+    Criteria floorCrit = crit.createCriteria("floors");
+    Criteria officeCrit = floorCrit.createCriteria("offices");
+    officeCrit.add(Restrictions.eq("label", "LAHGE"));
+    // now how we execute the query via the floorcrit
+    List<Building> l = list(officeCrit);
+    assertEquals(2, l.size());
+  }
+
+  public void testProjection() {
+    Criteria crit = session.createCriteria(Building.class).setProjection(Projections.rowCount());
+    Criteria floorCrit = crit.createCriteria("floors");
+    Criteria officeCrit = floorCrit.createCriteria("offices");
+    officeCrit.add(Restrictions.eq("label", "LAHGE"));
+    // now how we execute the query via the floorcrit
+    List<Integer> l = list(officeCrit);
+    assertEquals(1, l.size());
+    int total = 0;
+    for(int shardTotal : l) {
+      total += shardTotal;
+    }
+    assertEquals(2, total);
+  }
+
+  public void testMaxResults() throws Exception {
+    Criteria crit = session.createCriteria(Building.class).setMaxResults(1);
+    assertEquals(1, list(crit).size());
+  }
+
+  public void testAggregateProjection() throws Exception {
+    Criteria crit = session.createCriteria(Floor.class).setProjection(Projections.sum("number"));
+    List<Integer> l = list(crit);
+    assertEquals(1, l.size());
+    assertEquals(new BigDecimal(7), l.get(0));
+  }
+
+  public void testMultiExitOperations() throws Exception {
+    session.beginTransaction();
+    Building b = ModelDataFactory.building("Only Has Floors from 199-210");
+    ModelDataFactory.floor(b, 199);
+    ModelDataFactory.floor(b, 200);
+    ModelDataFactory.floor(b, 201);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    Criteria crit = session.createCriteria(Floor.class);
+    crit.addOrder(Order.asc("number")).setFirstResult(2).setMaxResults(3).setProjection(Projections.sum("number"));
+    List<Integer> l = list(crit);
+    assertEquals(1, l.size());
+    assertEquals(new BigDecimal(204), l.get(0));
+  }
+
+  public void testMultiOrdering() throws Exception {
+    Criteria crit = session.createCriteria(Office.class);
+    crit.addOrder(Order.asc("label")).addOrder(Order.desc("floor.building.name"));
+    List<Office> l = list(crit);
+    List<Office> answer = Lists.newArrayList(b2f1o1, b1f3o1, b1f3o2);
+    assertTrue(answer.equals(l));
+  }
+
+  private <T> List<T> list(Criteria crit) {
+    return crit.list();
+  }
+
+  private <T> T uniqueResult(Criteria crit) {
+    return (T) crit.uniqueResult();
+  }
+}
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.model.Elevator;
+import org.hibernate.shards.model.Escalator;
+import org.hibernate.shards.model.Floor;
+import org.hibernate.shards.model.Tenant;
+import org.hibernate.shards.model.Person;
+import org.hibernate.shards.model.Office;
+import org.hibernate.shards.model.Window;
+
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ModelDataFactory {
+  public static Building building(String name) {
+    Building b = new Building();
+    b.setName(name);
+    return b;
+  }
+
+  public static Escalator escalator(Floor bottom, Floor top) {
+    Escalator esc = new Escalator();
+    esc.setBottomFloor(bottom);
+    if(bottom != null) {
+      bottom.setGoingUp(esc);
+    }
+    esc.setTopFloor(top);
+    if(top != null) {
+      top.setGoingDown(esc);
+    }
+    return esc;
+  }
+
+  public static Floor floor(Building b, int number) {
+    return floor(b, number, null, null);
+  }
+
+  public static Floor floor(Building b, int number, Escalator up, Escalator down) {
+    Floor f = new Floor();
+    f.setBuilding(b);
+    b.getFloors().add(f);
+    f.setNumber(number);
+    f.setGoingDown(down);
+    f.setGoingUp(up);
+    return f;
+  }
+
+  public static Elevator elevator(Building b, Floor... floors) {
+    Elevator elev = new Elevator();
+    elev.setBuilding(b);
+    b.getElevators().add(elev);
+    for(Floor f : floors) {
+      f.getElevators().add(elev);
+    }
+    return elev;
+  }
+
+  public static Tenant tenant(String name, List<Building> buildings, List<Person> employees) {
+    Tenant t = new Tenant();
+    t.setName(name);
+    t.setBuildings(buildings);
+    if(buildings != null) {
+      for(Building b : buildings) {
+        b.getTenants().add(t);
+      }
+    }
+    t.setEmployees(employees);
+    if(employees != null) {
+      for(Person p : employees) {
+        p.setEmployer(t);
+      }
+    }
+    return t;
+  }
+
+  public static Person person(String name, Tenant employer) {
+    Person p = new Person();
+    p.setName(name);
+    p.setEmployer(employer);
+    if(employer != null) {
+      employer.getEmployees().add(p);
+    }
+    return p;
+  }
+
+  public static Office office(String label, Floor floor) {
+    Office o = new Office();
+    o.setLabel(label);
+    o.setFloor(floor);
+    floor.getOffices().add(o);
+    return o;
+  }
+
+  public static Window window(boolean opens) {
+    Window w = new Window();
+    w.setOpens(opens);
+    return w;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,868 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.integration.BaseShardingIntegrationTestCase;
+import org.hibernate.shards.integration.MemoryLeakPlugger;
+import static org.hibernate.shards.integration.model.ModelDataFactory.building;
+import static org.hibernate.shards.integration.model.ModelDataFactory.elevator;
+import static org.hibernate.shards.integration.model.ModelDataFactory.escalator;
+import static org.hibernate.shards.integration.model.ModelDataFactory.floor;
+import static org.hibernate.shards.integration.model.ModelDataFactory.office;
+import static org.hibernate.shards.integration.model.ModelDataFactory.person;
+import static org.hibernate.shards.integration.model.ModelDataFactory.tenant;
+import static org.hibernate.shards.integration.model.ModelDataFactory.window;
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.model.Escalator;
+import org.hibernate.shards.model.Floor;
+import org.hibernate.shards.model.Office;
+import org.hibernate.shards.model.Person;
+import org.hibernate.shards.model.Tenant;
+import org.hibernate.shards.model.Window;
+import org.hibernate.shards.session.ShardedSessionFactory;
+import org.hibernate.shards.session.ShardedSessionImpl;
+import org.hibernate.shards.session.SubsetShardedSessionFactoryImpl;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.strategy.ShardStrategyFactoryDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Sets;
+
+import org.hibernate.HibernateException;
+import org.hibernate.SessionFactory;
+import org.hibernate.TransactionException;
+import org.hibernate.classic.Session;
+import org.hibernate.criterion.Projections;
+import org.hibernate.proxy.HibernateProxy;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ModelPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  /*
+  @Override
+  protected int getNumDatabases() {
+    return 3;
+  }
+
+  @Override
+  protected int getNumShards() {
+    return 9;
+  }
+
+  @Override
+  protected boolean isVirtualShardingEnabled() {
+    return true;
+  }
+
+  @Override
+  protected IdGenType getIdGenType() {
+    return IdGenType.SHARD_UUID;
+  }
+  */
+
+  public void testMapping() {
+    // if we succeed, our model is ok
+  }
+
+  public void testBuildingLifecycle() {
+    session.beginTransaction();
+    Set<Building> buildings = Sets.newHashSet();
+    // we're using the round robin shard selector so we should
+    // end up with 2 buildings per shard
+    for(int i = 0; i < getNumShards() * 2; i++) {
+      Building b = building("building" + i);
+      Floor f1 = floor(b, 1);
+      Floor f2 = floor(b, 2);
+      Floor f3 = floor(b, 3);
+      escalator(f1, f2);
+      elevator(b, f1, f2, f3);
+      elevator(b, f1, f2, f3);
+      session.save(b);
+      buildings.add(b);
+    }
+    session.getTransaction().commit();
+    resetSession();
+    List<Integer> counts =  session.createCriteria(Building.class).setProjection(Projections.rowCount()).list();
+    int total = 0;
+    for(Integer count : counts) {
+      total += count;
+    }
+    assertEquals(getNumShards() * 2, total);
+    session.beginTransaction();
+    Map<ShardId, List<Serializable>> shards = Maps.newHashMap();
+    for(Building b : buildings) {
+      Building bReloaded = reloadAssertNotNull(b);
+      assertEquals(b.getName(), bReloaded.getName());
+      assertEquals(b.getFloors().size(), bReloaded.getFloors().size());
+      for(int i = 0; i < b.getFloors().size(); i++) {
+        Floor bFloor = b.getFloors().get(i);
+        Floor bReloadedFloor = bReloaded.getFloors().get(i);
+        assertEquals(bFloor.getNumber(), bReloadedFloor.getNumber());
+        assertEquals(2, bReloadedFloor.getElevators().size());
+      }
+      assertNotNull(bReloaded.getFloors().get(0).getGoingUp());
+      assertNull(bReloaded.getFloors().get(0).getGoingDown());
+      assertNull(bReloaded.getFloors().get(1).getGoingUp());
+      assertNotNull(bReloaded.getFloors().get(1).getGoingDown());
+
+      assertEquals(b.getElevators().size(), bReloaded.getElevators().size());
+      ShardId shardIdForObject = getShardIdForObject(bReloaded);
+      assertNotNull(shardIdForObject);
+      assertBuildingSubObjectsOnSameShard(bReloaded);
+      List<Serializable> idList = shards.get(shardIdForObject);
+      if(idList == null) {
+        idList = Lists.newArrayList();
+        shards.put(shardIdForObject, idList);
+      }
+      idList.add(bReloaded.getBuildingId());
+      bReloaded.setName(bReloaded.getName() + " updated");
+      for(Floor newFloor : bReloaded.getFloors()) {
+        newFloor.setNumber(newFloor.getNumber() + 33);
+      }
+    }
+    assertEquals(getNumShards(), shards.size());
+    for(List<Serializable> idList : shards.values()) {
+      assertEquals(2, idList.size());
+    }
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    for(Building b : buildings) {
+      Building bReloaded = reloadAssertNotNull(b);
+      assertNotNull(bReloaded);
+      assertEquals(b.getName() + " updated", bReloaded.getName());
+      for(int i = 0; i < b.getFloors().size(); i++) {
+        Floor bFloor = b.getFloors().get(i);
+        Floor bReloadedFloor = bReloaded.getFloors().get(i);
+        assertEquals(33 + bFloor.getNumber(), bReloadedFloor.getNumber());
+      }
+      ShardId shardIdForObject = getShardIdForObject(bReloaded);
+      // make sure the object resides on the same shard as before
+      assertTrue(shards.get(shardIdForObject).contains(b.getBuildingId()));
+      assertBuildingSubObjectsOnSameShard(bReloaded);
+      // now let's get rid of the buildings
+      session.delete(bReloaded);
+    }
+    session.getTransaction().commit();
+    resetSession();
+    for(Building b : buildings) {
+      assertNull(reload(b));
+      for(Floor f : b.getFloors()) {
+        assertNull(reload(f));
+      }
+    }
+  }
+
+  public void testSaveOrUpdate() {
+    session.beginTransaction();
+    Building b = building("b");
+    floor(b, 23);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    b.setName("b2");
+    session.saveOrUpdate(b);
+    session.getTransaction().commit();
+  }
+
+  public void testSavingOneToManyChildViaCascade() {
+    session.beginTransaction();
+    Building b = building("awesome building");
+    Floor f = floor(b, 23);
+    session.save(b);
+    session.getTransaction().commit();
+    assertBuildingSubObjectsOnSameShard(b);
+    assertOnSameShard(b, f);
+    resetSession();
+    assertNotNull(reload(b));
+    assertNotNull(reload(f));
+  }
+
+  /**
+   * In this test we demonstrate our ability to create a parent and a child by
+   * calling save on them individually (no cascading involved).  The key here
+   * is that both objects need to end up in the same shard.
+   */
+  public void testSavingOneToManyChildSeparatelyInSameSession() {
+    session.beginTransaction();
+    Building b = building("awesome building");
+    session.save(b);
+    Floor f = floor(b, 23);
+    session.save(f);
+    session.getTransaction().commit();
+    assertBuildingSubObjectsOnSameShard(b);
+    assertOnSameShard(b, f);
+  }
+
+  /**
+   * In this test we demonstrate our ability to create a parent and a child by
+   * calling save on them individually in separate sessions(no cascading involved).  The key here
+   * is that both objects need to end up in the same shard.
+   */
+  public void testSavingOneToManyChildSeparatelyInDifferentSessions() {
+    session.beginTransaction();
+    Building b = building("awesome building");
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    Floor f = floor(b, 23);
+    session.save(f);
+    session.getTransaction().commit();
+    assertBuildingSubObjectsOnSameShard(b);
+    assertOnSameShard(b, f);
+  }
+
+  /**
+   * In this test we demonstrate that if you try to save an entity that doesn't
+   * support top-level saves before associating some other object with that
+   * entity, you'll get an exception.
+   */
+  public void testSavingOneToOneChildWithoutAssociationFails() {
+    session.beginTransaction();
+    Escalator esc = escalator(null, null);
+    try {
+      session.save(esc);
+      fail("expected he");
+    } catch (HibernateException he) {
+      // good;
+    }
+  }
+
+  /**
+   * In this test we demonstrate that if you try to save an entity that doesn't
+   * support top-level saves after associating some other object with that
+   * entity, you'll be cool.
+   */
+  public void testSavingOneToOneChildWithAssociationSucceeds() {
+    session.beginTransaction();
+    Building b = building("hi");
+    Floor f = floor(b, 23);
+    session.save(b);
+    // now there is a session associated with the building and the floor
+    Escalator esc = escalator(f, null);
+    session.save(esc);
+    assertBuildingSubObjectsOnSameShard(b);
+    assertOnSameShard(b, f, esc);
+    session.getTransaction().commit();
+  }
+
+  public void testUpdatingOneToOneWithObjectFromWrongShardFailsOnSave() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    Floor f = floor(b, 23);
+    session.save(b);
+    // now there is a session associated with the building and the floor
+    Escalator esc = escalator(f, null);
+    session.save(esc);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(f.getGoingUp())));
+    resetSession();
+    session.beginTransaction();
+    f = reloadAssertNotNull(f);
+    f2 = reloadAssertNotNull(f2);
+    f2.setGoingUp(f.getGoingUp());
+    try {
+      session.save(f2);
+      session.getTransaction().commit();
+      fail("expected Hibernate Exception");
+    } catch (HibernateException he) {
+      // good
+    }
+    session.getTransaction().rollback();
+  }
+
+  public void testUpdatingOneToOneWithObjectFromWrongShardFailsOnCommitWithUnfetchedTarget() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    Floor f = floor(b, 23);
+    session.save(b);
+    // now there is a session associated with the building and the floor
+    Escalator esc = escalator(f, null);
+    session.save(esc);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(f.getGoingUp())));
+    resetSession();
+    session.beginTransaction();
+    f = reloadAssertNotNull(f);
+    f2 = reloadAssertNotNull(f2);
+    f2.setGoingUp(f.getGoingUp());
+    assertTrue(f.getGoingUp() instanceof HibernateProxy);
+    assertTrue(((HibernateProxy)f.getGoingUp()).getHibernateLazyInitializer().isUninitialized());
+    // note that we don't touch the escalator itself so that it is still a proxy
+    try {
+      session.getTransaction().commit();
+      fail("expected Transaction Exception");
+    } catch (TransactionException te) {
+      // good
+    }
+  }
+
+  public void testUpdatingOneToOneWithObjectFromWrongShardFailsOnCommitWithFetchedTarget() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    Floor f = floor(b, 23);
+    session.save(b);
+    // now there is a session associated with the building and the floor
+    Escalator esc = escalator(f, null);
+    session.save(esc);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(f.getGoingUp())));
+    resetSession();
+    session.beginTransaction();
+    f = reloadAssertNotNull(f);
+    f2 = reloadAssertNotNull(f2);
+    f2.setGoingUp(f.getGoingUp());
+    // forces lazy object to initialize.  Sadly, this has a meaningful effect
+    // on the behavior
+    f.getGoingUp().getBottomFloor();
+    try {
+      session.getTransaction().commit();
+      fail("expected Transaction Exception");
+    } catch (TransactionException tc) {
+      // good
+    }
+  }
+
+  public void testManyToOneCascade() {
+    session.beginTransaction();
+    Building b = building("b");
+    Floor f1 = floor(b, 1);
+    Floor f2 = floor(b, 2);
+    Escalator e = escalator(f1, f2);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    b = reloadAssertNotNull(b);
+    f1 = reloadAssertNotNull(f1);
+    f2 = reloadAssertNotNull(f2);
+    e = reloadAssertNotNull(e);
+    assertEquals(2, b.getFloors().size());
+    assertNotNull(b.getFloors().get(0).getGoingUp());
+    assertNotNull(b.getFloors().get(1).getGoingDown());
+    assertBuildingSubObjectsOnSameShard(b);
+    assertOnSameShard(b, f1, f2, e);
+  }
+
+  public void testUpdatingOneToManyWithObjectFromWrongShardFailsOnSave() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    floor(b, 23);
+    session.save(b);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(b).equals(getShardIdForObject(f2)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    f2 = reloadAssertNotNull(f2);
+    b.getFloors().add(f2);
+    try {
+      session.save(b);
+      session.getTransaction().commit();
+      fail("expected Hibernate Exception");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testUpdatingOneToManyWithObjectFromWrongShardFailsOnCommit() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    floor(b, 23);
+    session.save(b);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(b)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    f2 = reloadAssertNotNull(f2);
+    b.getFloors().add(f2);
+    // note that we don't touch the floor itself so that it is still a proxy
+    try {
+      session.getTransaction().commit();
+      fail("expected Transaction Exception");
+    } catch (TransactionException te) {
+      // good
+    }
+  }
+
+  public void testUpdatingManyToOneWithObjectFromWrongShardFailsOnSave() {
+    // test only applies if num dbs > 1
+    if(getNumDatabases() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    floor(b, 23);
+    session.save(b);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(b)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    f2 = reloadAssertNotNull(f2);
+    f2.setBuilding(b);
+    try {
+      session.save(f2);
+      session.getTransaction().commit();
+      fail("expected Hibernate Exception");
+    } catch (HibernateException he) {
+      // good, Hibernate detects that we're attempting to associate a collection
+      // with multiple sessions
+    }
+  }
+
+  public void testUpdatingManyToOneWithObjectFromWrongShardFailsOnCommit() {
+    // test only applies if num dbs > 1
+    if(getNumShards() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("hi");
+    floor(b, 23);
+    session.save(b);
+
+    Building b2 = building("hi2");
+    Floor f2 = floor(b2, 24);
+    session.save(b2);
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(f2).equals(getShardIdForObject(b)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    f2 = reloadAssertNotNull(f2);
+    f2.setBuilding(b);
+    // note that we don't touch the floor itself so that it is still a proxy
+    try {
+      session.getTransaction().commit();
+      fail("expected Transaction Exception");
+    } catch (TransactionException te) {
+      // good
+    }
+  }
+
+  public void testLockShard() {
+    session.beginTransaction();
+    session.lockShard();
+    Building b1 = building("b1");
+    session.save(b1);
+    Building b2 = building("b2");
+    session.save(b2);
+    session.getTransaction().commit();
+    assertOnSameShard(b1, b2);
+  }
+
+  public void testPerson() {
+    session.beginTransaction();
+    Person p = person("max", null);
+    Tenant t = tenant("tenant", null, Lists.newArrayList(p));
+    session.save(t);
+    session.getTransaction().commit();
+    resetSession();
+    p = reloadAssertNotNull(p);
+    assertEquals("max", p.getName());
+    t = reloadAssertNotNull(t);
+    assertOnSameShard(p, t);
+    assertTrue(t.getEmployees().contains(p));
+    // calling through to getTenantId() because of some weird cglib magic
+    assertEquals(p.getEmployer().getTenantId(), t.getTenantId());
+  }
+
+  public void testTenant() {
+    session.beginTransaction();
+    Tenant t = tenant("whaptech", null, null);
+    session.save(t);
+    Building b = building("b");
+    b.getTenants().add(t);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    t = reloadAssertNotNull(t);
+    assertEquals("whaptech", t.getName());
+    b = reloadAssertNotNull(b);
+    assertOnSameShard(b, t);
+    assertTrue(b.getTenants().contains(t));
+    assertTrue(t.getBuildings().contains(b));
+  }
+
+  public void testElevator() {
+    Building b = building("hi");
+    floor(b, 33);
+    session.beginTransaction();
+    session.save(b);
+    session.getTransaction().commit();
+
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(session, b);
+    Floor f = b.getFloors().get(0);
+    elevator(b, f);
+    session.getTransaction().commit();
+    resetSession();
+
+    b = reloadAssertNotNull(session, b);
+    assertEquals(1, b.getElevators().size());
+    assertEquals(b.getElevators().get(0), b.getFloors().get(0).getElevators().get(0));
+    resetSession();
+  }
+
+  public void testSavingManyToManyOnDifferentShardsFailsOnSave() {
+    if(getNumDatabases() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Tenant t = tenant("t", Collections.<Building>emptyList(), Collections.<Person>emptyList());
+    session.save(t);
+    Building b = building("b");
+    session.save(b);
+    Serializable bId = b.getBuildingId();
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(b).equals(getShardIdForObject(t)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    t = reloadAssertNotNull(t);
+    b.getTenants().add(t);
+    try {
+      session.save(b);
+      session.getTransaction().commit();
+      fail("expected Hibernate Exception");
+    } catch (HibernateException he) {
+      // good, Hibernate should recognize this as an attempt to associate
+      // a collection with two open sessions
+    }
+    resetSession();
+    b = (Building) session.get(Building.class, bId);
+    assertTrue(b.getTenants().isEmpty());
+  }
+
+  public void testSavingManyToManyOnDifferentShardsFailsOnCommit() {
+    if(getNumDatabases() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Tenant t = tenant("t", Collections.<Building>emptyList(), Collections.<Person>emptyList());
+    session.save(t);
+    Building b = building("b");
+    session.save(b);
+    Serializable bId = b.getBuildingId();
+    session.getTransaction().commit();
+    assertFalse("Should have been on different shards!", getShardIdForObject(t).equals(getShardIdForObject(b)));
+    resetSession();
+    session.beginTransaction();
+    b = reloadAssertNotNull(b);
+    t = reloadAssertNotNull(t);
+    b.getTenants().add(t);
+    try {
+      session.getTransaction().commit();
+      fail("Expected Transaction Exception");
+    } catch (TransactionException te) {
+      // good
+    }
+    resetSession();
+    b = (Building) session.get(Building.class, bId);
+    assertTrue(b.getTenants().isEmpty());
+  }
+
+  public void testParticularShardIds() throws Exception {
+    // store a couple of buildings on different shards
+    openSession();
+    for(int i=0; i<getNumShards(); i++) {
+      saveBuilding("building-"+i);
+    }
+    List<Building> buildings = session.createQuery("from Building").list();
+    assertEquals(getNumShards(), buildings.size());
+    resetSession();
+
+    ShardedSessionFactory ssf = (ShardedSessionFactory) session.getSessionFactory();
+
+    // desired shards
+    List<ShardId> shardIds = Lists.newArrayList(new ShardId((short) 0));
+
+    List<SessionFactory> allFactories = ssf.getSessionFactories();
+
+    MyShardStrategyFactory strategyFactoryMock = getMyMockStrategyFactory(shardIds);
+    ShardedSessionFactory ssfWithParticularShards = ssf.getSessionFactory(shardIds, strategyFactoryMock);
+
+    // need to make sure closing functionality is disabled.
+    assertTrue(ssfWithParticularShards instanceof SubsetShardedSessionFactoryImpl);
+    assertFalse(ssfWithParticularShards.isClosed());
+    ssfWithParticularShards.close();
+    assertFalse(ssfWithParticularShards.isClosed());
+
+    assertNotNull(ssfWithParticularShards);
+    // should not have kept track of this special factory
+    assertEquals(allFactories.size(), ssfWithParticularShards.getSessionFactories().size());
+
+    // did we use the new strategies?
+    assertEquals(shardIds, strategyFactoryMock.shardIds);
+
+    // do we only search certain shards?
+    // we should only get back the buildings that were on shard 0, i.e. a single building
+    Session sessionWithParticularShards = ssfWithParticularShards.openSession();
+    List<Building> buildingsFromDesiredShards = sessionWithParticularShards.createQuery("from Building").list();
+
+    if (!isVirtualShardingEnabled()) {
+      assertEquals(1, buildingsFromDesiredShards.size());
+    }
+
+    // clean up memory for this new unrecorded session
+    MemoryLeakPlugger.plug((ShardedSessionImpl) sessionWithParticularShards);
+    sessionWithParticularShards.close();
+  }
+
+  private void saveBuilding(String name) {
+    session.beginTransaction();
+    Building bForShard0 = building(name);
+    session.save(bForShard0);
+    session.getTransaction().commit();
+    resetSession();
+  }
+
+  private MyShardStrategyFactory getMyMockStrategyFactory(List<ShardId> shardIds) {
+    ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
+    MyShardStrategyFactory strategyFactoryMock = new MyShardStrategyFactory();
+    strategyFactoryMock.shardStrategyToReturn = shardStrategyFactory.newShardStrategy(shardIds);
+    return strategyFactoryMock;
+  }
+
+  public void testBadShardIds() throws Exception {
+    ShardedSessionFactory ssf = (ShardedSessionFactory) session.getSessionFactory();
+    // this shardId doesn't exist
+    List<ShardId> shardIds = Lists.newArrayList(new ShardId((short) -1));
+    try {
+      ssf.getSessionFactory(shardIds, new MyShardStrategyFactory());
+      fail("ShardedSessionFactory accepted an invalid shardId");
+    } catch (IllegalStateException e) {
+      // good
+    }
+  }
+
+  static class MyShardStrategyFactory extends ShardStrategyFactoryDefaultMock {
+
+    List<ShardId> shardIds;
+    ShardStrategy shardStrategyToReturn = null;
+
+    @Override
+
+    public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+      this.shardIds = shardIds;
+      return shardStrategyToReturn;
+    }
+  }
+
+
+  public void testBuildingWithWindowCascadeOnSave() {
+    session.beginTransaction();
+    Building b = building("b1");
+    Floor f = floor(b, 23);
+    Office o = office("88-b", f);
+    o.setWindow(window(false));
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    b = reload(b);
+    assertNotNull(b.getFloors().get(0).getOffices().get(0).getWindow());
+  }
+
+  public void testBuildingWithWindowNoCascadeOnUpdate() {
+    session.beginTransaction();
+    Building b = building("b1");
+    Floor f = floor(b, 23);
+    office("88-b", f);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    b.getFloors().get(0).getOffices().get(0).setWindow(window(false));
+    session.getTransaction().commit();
+    b = reload(b);
+    assertNotNull(b.getFloors().get(0).getOffices().get(0).getWindow());
+  }
+
+  public void testBuildingWithWindowNoCascadeFailsOnSave() {
+    // test only applies if num dbs > 1
+    if(getNumDatabases() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("b1");
+    Floor f = floor(b, 23);
+    office("88-b", f);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    Window w = window(false);
+    session.save(w);
+    Office o = b.getFloors().get(0).getOffices().get(0);
+    assertFalse("Should have been on different shards!", getShardIdForObject(o).equals(getShardIdForObject(w)));
+    o.setWindow(w);
+    try {
+      session.save(o);
+      session.getTransaction().commit();
+      fail("expected Hibernate Exception");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testBuildingWithWindowNoCascadeFailsOnCommit() {
+    // test only applies if num dbs > 1
+    if(getNumDatabases() == 1) {
+      return;
+    }
+    session.beginTransaction();
+    Building b = building("b1");
+    Floor f = floor(b, 23);
+    office("88-b", f);
+    session.save(b);
+    session.getTransaction().commit();
+    resetSession();
+    session.beginTransaction();
+    b = reload(b);
+    Window w = window(false);
+    session.save(w);
+    assertFalse("Should have been on different shards!", getShardIdForObject(b).equals(getShardIdForObject(w)));
+    b.getFloors().get(0).getOffices().get(0).setWindow(w);
+    try {
+      session.getTransaction().commit();
+      fail("expected Transaction Exception");
+    } catch (TransactionException te) {
+      // good
+    }
+  }
+
+  private void assertOnSameShard(Object... objs) {
+    for(int i = 0; i < objs.length - 1; i++) {
+      assertEquals(getShardIdForObject(objs[i]), getShardIdForObject(objs[i + 1]));
+    }
+  }
+
+  private void assertBuildingSubObjectsOnSameShard(Building b) {
+    List<Object> subObjects = Lists.<Object>newArrayList(b);
+    subObjects.addAll(b.getFloors());
+    for(Floor f : b.getFloors()) {
+      addIfNotNull(subObjects, f.getGoingUp());
+      addIfNotNull(subObjects, f.getGoingDown());
+      subObjects.addAll(f.getOffices());
+    }
+    subObjects.addAll(b.getElevators());
+    subObjects.addAll(b.getTenants());
+    subObjects.addAll(b.getTenants());
+    for(Tenant t : b.getTenants()) {
+      subObjects.addAll(t.getEmployees());
+    }
+    assertOnSameShard(subObjects);
+  }
+
+  private void addIfNotNull(List<Object> subObjects, Object obj) {
+    if(obj != null) {
+      subObjects.add(obj);
+    }
+  }
+
+  // this is a really good way to shake out synchronization bugs
+  public void xtestOverAndOver() throws Exception {
+    final boolean[] go = {true};
+    Runnable r = new Runnable() {
+      public void run() {
+        while(go[0]) {
+          try {
+            Thread.sleep(5000);
+          } catch (InterruptedException e) {
+            // fine
+          }
+        }
+      }
+    };
+    new Thread(r).start();
+    tearDown();
+    for(int i = 0; i < 100; i++) {
+      setUp();
+      try {
+        testBuildingLifecycle();
+      } finally {
+        tearDown();
+      }
+    }
+    go[0] = false;
+  }
+}
+
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelQueryPermutedIntegrationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelQueryPermutedIntegrationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/model/ModelQueryPermutedIntegrationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,150 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.model;
+
+import org.hibernate.shards.integration.BaseShardingIntegrationTestCase;
+import org.hibernate.shards.model.Building;
+import org.hibernate.shards.model.Floor;
+import org.hibernate.shards.model.Office;
+
+import org.hibernate.Query;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ModelQueryPermutedIntegrationTest extends BaseShardingIntegrationTestCase {
+
+  private Building b1;
+  private Floor b1f1;
+  private Floor b1f2;
+  private Floor b1f3;
+  private Office b1f3o1;
+  private Office b1f3o2;
+
+  private Building b2;
+  private Floor b2f1;
+  private Office b2f1o1;
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    session.beginTransaction();
+    b1 = ModelDataFactory.building("b1");
+    b1f1 = ModelDataFactory.floor(b1, 1);
+    b1f2 = ModelDataFactory.floor(b1, 2);
+    b1f3 = ModelDataFactory.floor(b1, 3);
+    b1f3o1 = ModelDataFactory.office("NOT LAHGE", b1f3);
+    b1f3o2 = ModelDataFactory.office("LAHGE", b1f3);
+    session.save(b1);
+
+    b2 = ModelDataFactory.building("b2");
+    b2f1 = ModelDataFactory.floor(b2, 1);
+    b2f1o1 = ModelDataFactory.office("LAHGE", b2f1);
+    session.save(b2);
+    session.getTransaction().commit();
+    resetSession();
+    b1 = reload(b1);
+    b1f1 = reload(b1f1);
+    b1f2 = reload(b1f2);
+    b1f3 = reload(b1f3);
+    b1f3o1 = reload(b1f3o1);
+    b1f3o2 = reload(b1f3o2);
+    b2 = reload(b2);
+    b2f1 = reload(b2f1);
+    b2f1o1 = reload(b2f1o1);
+  }
+
+  @Override
+  protected void tearDown() throws Exception {
+    b1 = null;
+    b1f1 = null;
+    b1f2 = null;
+    b1f3 = null;
+    b1f3o1 = null;
+    b1f3o2 = null;
+    b2 = null;
+    b2f1 = null;
+    b2f1o1 = null;
+    super.tearDown();
+  }
+
+  public void testLoadAllBuildings() throws Exception {
+    String queryString = "from Building";
+    Query query = session.createQuery(queryString);
+    List<Building> buildings = query.list();
+    assertEquals(2, buildings.size());
+    assertTrue(buildings.contains(b1));
+    assertTrue(buildings.contains(b2));
+  }
+
+  public void testLoadBuildingByName() throws Exception {
+    String queryString = "from Building as b where b.name=:name";
+    Query query = session.createQuery(queryString).setString("name", "b2");
+    Building b2Reloaded = (Building) query.uniqueResult();
+    assertEquals(b2.getBuildingId(), b2Reloaded.getBuildingId());
+  }
+
+  public void testLoadBuildingsByLikeName() throws Exception {
+    String queryString = "from Building as b where b.name like :name";
+    Query query = session.createQuery(queryString).setString("name", "b%");
+    List<Building> buildings = query.list();
+    assertEquals(2, buildings.size());
+    assertTrue(buildings.contains(b1));
+    assertTrue(buildings.contains(b2));
+  }
+
+  public void testLoadHighFloors() throws Exception {
+    String queryString = "from Floor as f where f.number >= 3";
+    Query query = session.createQuery(queryString);
+    List<Floor> floors = query.list();
+    assertEquals(1, floors.size());
+  }
+
+  public void testLoadBuildingsWithHighFloors() throws Exception {
+    String queryString = "from Floor as f where f.number >= 3";
+    Query query = session.createQuery(queryString);
+    List<Floor> floors = query.list();
+    assertEquals(1, floors.size());
+  }
+
+  public void testLoadBuildingsWithHighFloorsAndLargeOffices() throws Exception {
+    String queryString = "from Building b join b.floors floor join floor.offices office where office.label = 'LAHGE'";
+    Query query = session.createQuery(queryString);
+    List<Building> buildings = query.list();
+    assertEquals(2, buildings.size());
+  }
+
+  public void testNamedQuery() {
+    Query query = session.getNamedQuery("SelectFloorsHigherThan");
+    query.setInteger("lowestFloor", 3);
+    List<Floor> floors = query.list();
+    assertEquals(1, floors.size());
+  }
+
+  public void xtestAggregating() throws Exception {
+    //TODO(maulik) make this test work
+    String queryString = "min(floor.number) from Floor floor";
+    Query query = session.createQuery(queryString);
+    List<Building> buildings = query.list();
+    assertEquals(2, buildings.size());
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/package-info.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/package-info.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/package-info.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration;

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/BaseDatabasePlatform.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/BaseDatabasePlatform.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/BaseDatabasePlatform.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.platform;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public abstract class BaseDatabasePlatform implements DatabasePlatform {
+
+  protected BaseDatabasePlatform() {
+    try {
+      Class.forName(getDriverClass());
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  protected abstract String getDriverClass();
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatform.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatform.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatform.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.platform;
+
+import org.hibernate.shards.integration.IdGenType;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface DatabasePlatform {
+  String getName();
+  Iterable<String> getCreateTableStatements(IdGenType idGenType);
+  Iterable<String> getDropTableStatements(IdGenType idGenType);
+  String getUrl(int index);
+  String getUser();
+  String getPassword();
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatformFactory.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatformFactory.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/DatabasePlatformFactory.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,52 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.platform;
+
+import org.hibernate.shards.integration.platform.hsql.HSQLDatabasePlatform;
+import org.hibernate.shards.util.StringUtil;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public interface DatabasePlatformFactory {
+  DatabasePlatform getDatabasePlatform();
+
+  DatabasePlatformFactory FACTORY = new DatabasePlatformFactory() {
+    public DatabasePlatform getDatabasePlatform() {
+      String platformClassStr = System.getProperty("hibernate.shard.database.platform");
+      if(StringUtil.isEmptyOrWhitespace(platformClassStr)) {
+        return getDefaultPlatform();
+      }
+      try {
+        Class clazz = Class.forName(platformClassStr);
+        return (DatabasePlatform) clazz.newInstance();
+      } catch (ClassNotFoundException e) {
+        throw new RuntimeException("Unknown platform class", e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException("Could not access platform class", e);
+      } catch (InstantiationException e) {
+        throw new RuntimeException("Could not instantiate platform class", e);
+      }
+    }
+
+    private DatabasePlatform getDefaultPlatform() {
+      return HSQLDatabasePlatform.getInstance();
+    }
+  };
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.platform.hsql;
+
+import org.hibernate.shards.integration.IdGenType;
+import org.hibernate.shards.integration.platform.BaseDatabasePlatform;
+import org.hibernate.shards.integration.platform.DatabasePlatform;
+import org.hibernate.shards.util.Lists;
+
+import org.hsqldb.jdbcDriver;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class HSQLDatabasePlatform extends BaseDatabasePlatform {
+
+  private static final String DRIVER_CLASS = jdbcDriver.class.getName();
+  private static final String IN_MEMORY_DB_URL_PREFIX = "jdbc:hsqldb:mem:";
+  private static final String IN_MEMORY_DB_USER = "sa";
+  private static final String IN_MEMORY_DB_PASSWORD = "";
+
+  protected static final DatabasePlatform PLATFORM = new HSQLDatabasePlatform();
+
+
+  private static final Iterable<String> CREATE_TABLE_STATEMENTS = Lists.newArrayList(
+     "CREATE TABLE sample_table (id DECIMAL(40,0) PRIMARY KEY, str_col VARCHAR(256))"
+    ,"CREATE TABLE sample_table2 (id DECIMAL(40,0) PRIMARY KEY, str_col VARCHAR(256))"
+    ,"CREATE TABLE hibernate_unique_key (id IDENTITY, next_hi DECIMAL(40,0))"
+    ,"INSERT INTO hibernate_unique_key(next_hi) VALUES(1)"
+    ,"CREATE TABLE Elevator (elevatorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0))"
+    ,"CREATE TABLE Building (buildingId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
+    ,"CREATE TABLE Floor (floorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0), upEscalatorId DECIMAL(40,0), downEscalatorId DECIMAL(40,0), number DECIMAL(40,0))"
+    ,"CREATE TABLE Tenant (tenantId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
+    ,"CREATE TABLE BuildingTenant (buildingId DECIMAL(40,0), tenantId DECIMAL(40,0), PRIMARY KEY(buildingId, tenantId))"
+    ,"CREATE TABLE Office (officeId DECIMAL(40,0) PRIMARY KEY, floorId DECIMAL(40,0), label VARCHAR(50), windowId DECIMAL(40,0))"
+    ,"CREATE TABLE Window (windowId DECIMAL(40,0) PRIMARY KEY, opens DECIMAL(5,0))"
+    ,"CREATE TABLE FloorElevator (floorId DECIMAL(40,0), elevatorId DECIMAL(40,0), PRIMARY KEY(floorId, elevatorId))"
+    ,"CREATE TABLE Escalator (escalatorId DECIMAL(40,0) PRIMARY KEY, bottomFloorId DECIMAL(40,0), topFloorId DECIMAL(40,0))"
+    ,"CREATE TABLE Person (personId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50), tenantId DECIMAL(40,0), officeId DECIMAL(40,0))"
+  );
+
+  protected static final List<String> DROP_TABLE_STATEMENTS = Lists.newArrayList(
+      "SHUTDOWN" // this deletes the whole database!
+  );
+
+  protected HSQLDatabasePlatform() {
+    try {
+      Class.forName(DRIVER_CLASS);
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public Iterable<String> getCreateTableStatements(IdGenType idGenType) {
+    return CREATE_TABLE_STATEMENTS;
+  }
+
+  public Iterable<String> getDropTableStatements(IdGenType idGenType) {
+    return DROP_TABLE_STATEMENTS;
+  }
+
+  public static DatabasePlatform getInstance() {
+    return PLATFORM;
+  }
+
+  public String getUrl(int index) {
+    return IN_MEMORY_DB_URL_PREFIX + "shard" + index;
+  }
+
+  public String getUser() {
+    return IN_MEMORY_DB_USER;
+  }
+
+  public String getPassword() {
+    return IN_MEMORY_DB_PASSWORD;
+  }
+
+  public String getName() {
+    return "hsql";
+  }
+
+  @Override
+  protected String getDriverClass() {
+    return DRIVER_CLASS;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,128 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,128 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,128 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard0.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard0.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard0.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory name="HibernateSessionFactory0">
+    <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+    <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+    <property name="connection.url">jdbc:hsqldb:mem:shard0</property>
+    <property name="connection.username">sa</property>
+    <property name="connection.password"></property>
+    <property name="hibernate.connection.shard_id">0</property>
+    <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+  </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard1.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard1.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard1.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+    <session-factory name="HibernateSessionFactory1">
+      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+      <property name="connection.url">jdbc:hsqldb:mem:shard1</property>
+      <property name="connection.username">sa</property>
+      <property name="connection.password"></property>
+      <property name="hibernate.connection.shard_id">1</property>
+      <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+    </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard2.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard2.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/hsql/config/shard2.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory name="HibernateSessionFactory2">
+      <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+      <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+      <property name="connection.url">jdbc:hsqldb:mem:shard2</property>
+      <property name="connection.username">sa</property>
+      <property name="connection.password"></property>
+      <property name="hibernate.connection.shard_id">2</property>
+      <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+  </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/MySQLDatabasePlatform.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/MySQLDatabasePlatform.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/MySQLDatabasePlatform.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,104 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.integration.platform.mysql;
+
+import com.mysql.jdbc.Driver;
+
+import org.hibernate.shards.integration.IdGenType;
+import org.hibernate.shards.integration.platform.BaseDatabasePlatform;
+import org.hibernate.shards.integration.platform.DatabasePlatform;
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class MySQLDatabasePlatform extends BaseDatabasePlatform {
+  private static final String DRIVER_CLASS = Driver.class.getName();
+  private static final String DB_URL_PREFIX = "jdbc:mysql://localhost:3306/shard";
+  private static final String DB_USER = "shard_user";
+  private static final String DB_PASSWORD = "shard";
+
+  protected static final DatabasePlatform PLATFORM = new MySQLDatabasePlatform();
+
+  private static final Iterable<String> CREATE_TABLE_STATEMENTS = Lists.newArrayList(
+     "CREATE TABLE hibernate_unique_key (id DECIMAL(40,0) PRIMARY KEY, next_hi DECIMAL(40,0))"
+    ,"INSERT INTO hibernate_unique_key(next_hi) VALUES(1)"
+    ,"CREATE TABLE sample_table (id DECIMAL(40,0) PRIMARY KEY, str_col VARCHAR(256))"
+    ,"CREATE TABLE sample_table2 (id DECIMAL(40,0) PRIMARY KEY, str_col VARCHAR(256))"
+    ,"CREATE TABLE Elevator (elevatorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0))"
+    ,"CREATE TABLE Building (buildingId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
+    ,"CREATE TABLE Floor (floorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0), upEscalatorId DECIMAL(40,0), downEscalatorId DECIMAL(40,0), number DECIMAL(40,0))"
+    ,"CREATE TABLE Tenant (tenantId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
+    ,"CREATE TABLE BuildingTenant (buildingId DECIMAL(40,0), tenantId DECIMAL(40,0), PRIMARY KEY(buildingId, tenantId))"
+    ,"CREATE TABLE Office (officeId DECIMAL(40,0) PRIMARY KEY, floorId DECIMAL(40,0), label VARCHAR(50))"
+    ,"CREATE TABLE FloorElevator (floorId DECIMAL(40,0), elevatorId DECIMAL(40,0), PRIMARY KEY(floorId, elevatorId))"
+    ,"CREATE TABLE Escalator (escalatorId DECIMAL(40,0) PRIMARY KEY, bottomFloorId DECIMAL(40,0), topFloorId DECIMAL(40,0))"
+    ,"CREATE TABLE Person (personId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50), tenantId DECIMAL(40,0), officeId DECIMAL(40,0))"
+  );
+
+  protected static final List<String> DROP_TABLE_STATEMENTS = Lists.newArrayList(
+      "DROP TABLE hibernate_unique_key",
+      "DROP TABLE sample_table",
+      "DROP TABLE sample_table2",
+      "DROP TABLE Elevator",
+      "DROP TABLE Building",
+      "DROP TABLE Floor",
+      "DROP TABLE Tenant",
+      "DROP TABLE BuildingTenant",
+      "DROP TABLE Office",
+      "DROP TABLE FloorElevator",
+      "DROP TABLE Escalator",
+      "DROP TABLE Person"
+  );
+
+  public Iterable<String> getCreateTableStatements(IdGenType idGenType) {
+    return CREATE_TABLE_STATEMENTS;
+  }
+
+  public Iterable<String> getDropTableStatements(IdGenType idGenType) {
+    return DROP_TABLE_STATEMENTS;
+  }
+
+  public static DatabasePlatform getInstance() {
+    return PLATFORM;
+  }
+
+  public String getUrl(int index) {
+    return DB_URL_PREFIX + index;
+  }
+
+  public String getUser() {
+    return DB_USER;
+  }
+
+  public String getPassword() {
+    return DB_PASSWORD;
+  }
+
+  public String getName() {
+    return "mysql";
+  }
+
+  @Override
+  protected String getDriverClass() {
+    return DRIVER_CLASS;
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,128 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="long">
+      <generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,127 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,127 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="org.hibernate.shards.model">
+
+  <class name="Building" table="Building">
+    <id name="buildingId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="floors" lazy="true" table="Floor" inverse="true" order-by="floorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Floor"/>
+    </bag>
+    <bag name="tenants" lazy="true" table="BuildingTenant" order-by="tenantId asc">
+      <key column="buildingId"/>
+      <many-to-many class="Tenant" column="tenantId"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="Elevator" inverse="true" order-by="elevatorId asc" cascade="all">
+      <key column="buildingId"/>
+      <one-to-many class="Elevator"/>
+    </bag>
+  </class>
+
+  <class name="Elevator">
+    <id name="elevatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="floors" lazy="true" table="FloorElevator" order-by="floorId asc">
+      <key column="elevatorId"/>
+      <many-to-many class="Floor" column="floorId"/>
+    </bag>
+  </class>
+
+  <class name="Escalator">
+    <id name="escalatorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <one-to-one name="bottomFloor" property-ref="goingUp"/>
+    <one-to-one name="topFloor" property-ref="goingUp"/>
+  </class>
+
+  <class name="Tenant">
+    <id name="tenantId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <bag name="buildings" lazy="true" table="BuildingTenant" order-by="buildingId asc">
+      <key column="tenantId"/>
+      <many-to-many class="Building" column="buildingId"/>
+    </bag>
+    <bag name="employees" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="tenantId"/>
+      <one-to-many class="Person"/>
+    </bag>
+  </class>
+
+  <class name="Person">
+    <id name="personId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="name" not-null="true"/>
+    <many-to-one name="employer" column="tenantId" not-null="false" class="Tenant"/>
+    <many-to-one name="office" column="officeId" not-null="false" class="Office"/>
+  </class>
+
+  <class name="Office">
+    <id name="officeId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="label" not-null="true"/>
+    <many-to-one name="floor" column="floorId" not-null="false" class="Floor"/>
+    <bag name="people" lazy="true" table="Person" inverse="true" order-by="personId asc" cascade="save-update">
+      <key column="officeId"/>
+      <one-to-many class="Person"/>
+    </bag>
+    <many-to-one name="window" column="windowId" unique="true" not-null="false" cascade="all"/>
+  </class>
+
+  <class name="Window">
+    <id name="windowId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="opens" not-null="true"/>
+  </class>
+
+  <class name="Floor">
+    <id name="floorId" type="big_integer">
+      <generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
+    </id>
+    <property name="number" not-null="true"/>
+    <many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
+    <many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
+    <bag name="offices" lazy="true" table="Office" inverse="true" order-by="officeId asc" cascade="all">
+      <key column="floorId"/>
+      <one-to-many class="Office"/>
+    </bag>
+    <bag name="elevators" lazy="true" table="FloorElevator" order-by="elevatorId asc">
+      <key column="floorId"/>
+      <many-to-many class="Elevator" column="elevatorId"/>
+    </bag>
+  </class>
+
+  <query name="SelectFloorsHigherThan">
+    <![CDATA[from Floor as f where f.number >= :lowestFloor]]>
+  </query>
+</hibernate-mapping>

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard0.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard0.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard0.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory name="HibernateSessionFactory0">
+    <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+    <property name="connection.url">jdbc:mysql://localhost:3306/shard0</property>
+    <property name="connection.username">shard_user</property>
+    <property name="connection.password">shard</property>
+    <property name="hibernate.connection.shard_id">0</property>
+    <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+  </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard1.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard1.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard1.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory name="HibernateSessionFactory0">
+    <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+    <property name="connection.url">jdbc:mysql://localhost:3306/shard1</property>
+    <property name="connection.username">shard_user</property>
+    <property name="connection.password">shard</property>
+    <property name="hibernate.connection.shard_id">1</property>
+    <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+  </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard2.hibernate.cfg.xml
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard2.hibernate.cfg.xml	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/integration/platform/mysql/config/shard2.hibernate.cfg.xml	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,34 @@
+<!--
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+-->
+
+<!DOCTYPE hibernate-configuration PUBLIC
+	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory name="HibernateSessionFactory0">
+    <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
+    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+    <property name="connection.url">jdbc:mysql://localhost:3306/shard2</property>
+    <property name="connection.username">shard_user</property>
+    <property name="connection.password">shard</property>
+    <property name="hibernate.connection.shard_id">2</property>
+    <property name="hibernate.shard.check_all_associated_objects_for_different_shards">true</property>
+  </session-factory>
+</hibernate-configuration>
+

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancerTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancerTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/RoundRobinShardLoadBalancerTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class RoundRobinShardLoadBalancerTest extends TestCase {
+
+  public void testBalancer() {
+    List<ShardId> shardIds = Lists.newArrayList(new ShardId(1), new ShardId(2));
+    RoundRobinShardLoadBalancer balancer = new RoundRobinShardLoadBalancer(shardIds);
+    assertEquals(0, balancer.getNextIndex());
+    assertEquals(1, balancer.getNextIndex());
+    assertEquals(0, balancer.getNextIndex());
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/ShardLoadBalancerDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/ShardLoadBalancerDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/loadbalance/ShardLoadBalancerDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.loadbalance;
+
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardLoadBalancerDefaultMock implements org.hibernate.shards.loadbalance.ShardLoadBalancer {
+
+  public ShardId getNextShardId() {
+    throw new UnsupportedOperationException();
+  }
+
+  public List<ShardId> getAllShardIds() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Building.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Building.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Building.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Building {
+
+  private Serializable buildingId;
+  private String name;
+  private List<Floor> floors = Lists.newArrayList();
+  private List<Tenant> tenants = Lists.newArrayList();
+  private List<Elevator> elevators = Lists.newArrayList();
+
+  public Serializable getBuildingId() {
+    return buildingId;
+  }
+
+  void setBuildingId(Serializable buildingId) {
+    this.buildingId = buildingId;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public List<Floor> getFloors() {
+    return floors;
+  }
+
+  public void setFloors(List<Floor> floors) {
+    this.floors = floors;
+  }
+
+  public List<Tenant> getTenants() {
+    return tenants;
+  }
+
+  public void setTenants(List<Tenant> tenants) {
+    this.tenants = tenants;
+  }
+
+  public List<Elevator> getElevators() {
+    return elevators;
+  }
+
+  public void setElevators(List<Elevator> elevators) {
+    this.elevators = elevators;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Building building = (Building)o;
+
+    if (buildingId != null ? !buildingId.equals(building.buildingId)
+        : building.buildingId != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (buildingId != null ? buildingId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Elevator.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Elevator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Elevator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Elevator {
+
+  private Serializable elevatorId;
+  private List<Floor> floors = Lists.newArrayList();
+  private Building building;
+
+  public Serializable getElevatorId() {
+    return elevatorId;
+  }
+
+  public void setElevatorId(Serializable elevatorId) {
+    this.elevatorId = elevatorId;
+  }
+
+  public List<Floor> getFloors() {
+    return floors;
+  }
+
+  public void setFloors(List<Floor> floors) {
+    this.floors = floors;
+  }
+
+  public Building getBuilding() {
+    return building;
+  }
+
+  public void setBuilding(Building building) {
+    this.building = building;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Elevator elevator = (Elevator)o;
+
+    if (elevatorId != null ? !elevatorId.equals(elevator.elevatorId)
+        : elevator.elevatorId != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (elevatorId != null ? elevatorId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Escalator.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Escalator.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Escalator.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,79 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Escalator {
+
+  private Serializable escalatorId;
+  private Floor bottomFloor;
+  private Floor topFloor;
+
+  public Serializable getEscalatorId() {
+    return escalatorId;
+  }
+
+  void setEscalatorId(Serializable escalatorId) {
+    this.escalatorId = escalatorId;
+  }
+
+  public Floor getBottomFloor() {
+    return bottomFloor;
+  }
+
+  public void setBottomFloor(Floor bottomFloor) {
+    this.bottomFloor = bottomFloor;
+  }
+
+  public Floor getTopFloor() {
+    return topFloor;
+  }
+
+  public void setTopFloor(Floor topFloor) {
+    this.topFloor = topFloor;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Escalator escalator = (Escalator)o;
+
+    if (escalatorId != null ? !escalatorId.equals(escalator.escalatorId)
+        : escalator.escalatorId != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (escalatorId != null ? escalatorId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Floor.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Floor.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Floor.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,127 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import org.hibernate.shards.util.Lists;
+
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Floor {
+
+  private Serializable floorId;
+  private int number;
+  private List<Tenant> tenants;
+  private List<Office> offices = Lists.newArrayList();
+  private List<Elevator> elevators = Lists.newArrayList();
+  private Escalator goingUp;
+  private Escalator goingDown;
+  private Building building;
+
+  public Serializable getFloorId() {
+    return floorId;
+  }
+
+  void setFloorId(Serializable floorId) {
+    this.floorId = floorId;
+  }
+
+  public int getNumber() {
+    return number;
+  }
+
+  public void setNumber(int number) {
+    this.number = number;
+  }
+
+  public List<Tenant> getTenants() {
+    return tenants;
+  }
+
+  public void setTenants(List<Tenant> tenants) {
+    this.tenants = tenants;
+  }
+
+  public List<Office> getOffices() {
+    return offices;
+  }
+
+  public void setOffices(List<Office> offices) {
+    this.offices = offices;
+  }
+
+  public List<Elevator> getElevators() {
+    return elevators;
+  }
+
+  public void setElevators(List<Elevator> elevators) {
+    this.elevators = elevators;
+  }
+
+  public Escalator getGoingUp() {
+    return goingUp;
+  }
+
+  public void setGoingUp(Escalator goingUp) {
+    this.goingUp = goingUp;
+  }
+
+  public Escalator getGoingDown() {
+    return goingDown;
+  }
+
+  public void setGoingDown(Escalator goingDown) {
+    this.goingDown = goingDown;
+  }
+
+  public Building getBuilding() {
+    return building;
+  }
+
+  public void setBuilding(Building building) {
+    this.building = building;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Floor floor = (Floor)o;
+
+    if (floorId != null ? !floorId.equals(floor.floorId) : floor.floorId != null)
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (floorId != null ? floorId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Office.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Office.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Office.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,95 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Office {
+
+  private Serializable officeId;
+  private String label;
+  private Floor floor;
+  private Window window;
+  private List<Person> people;
+
+  public Serializable getOfficeId() {
+    return officeId;
+  }
+
+  void setOfficeId(Serializable officeId) {
+    this.officeId = officeId;
+  }
+
+  public String getLabel() {
+    return label;
+  }
+
+  public void setLabel(String label) {
+    this.label = label;
+  }
+
+  public Floor getFloor() {
+    return floor;
+  }
+
+  public void setFloor(Floor floor) {
+    this.floor = floor;
+  }
+
+  public List<Person> getPeople() {
+    return people;
+  }
+
+  public void setPeople(List<Person> people) {
+    this.people = people;
+  }
+
+  public Window getWindow() {
+    return window;
+  }
+
+  public void setWindow(Window window) {
+    this.window = window;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Office office = (Office)o;
+
+    return !(officeId != null ? !officeId.equals(office.officeId)
+        : office.officeId != null);
+
+  }
+
+  @Override
+  public int hashCode() {
+    return (officeId != null ? officeId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Person.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Person.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Person.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Person {
+
+  private Serializable personId;
+  private String name;
+  private Office office;
+  private Tenant employer;
+
+  public Serializable getPersonId() {
+    return personId;
+  }
+
+  void setPersonId(Serializable personId) {
+    this.personId = personId;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public Office getOffice() {
+    return office;
+  }
+
+  public void setOffice(Office office) {
+    this.office = office;
+  }
+
+  public Tenant getEmployer() {
+    return employer;
+  }
+
+  public void setEmployer(Tenant employer) {
+    this.employer = employer;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Person person = (Person)o;
+
+    if (personId != null ? !personId.equals(person.personId)
+        : person.personId != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (personId != null ? personId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Tenant.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Tenant.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Tenant.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,89 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import java.util.List;
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class Tenant {
+
+  private Serializable tenantId;
+  private String name;
+  private List<Building> buildings;
+  private List<Person> employees;
+
+  public Serializable getTenantId() {
+    return tenantId;
+  }
+
+  void setTenantId(Serializable tenantId) {
+    this.tenantId = tenantId;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public List<Building> getBuildings() {
+    return buildings;
+  }
+
+  public void setBuildings(List<Building> buildings) {
+    this.buildings = buildings;
+  }
+
+  public List<Person> getEmployees() {
+    return employees;
+  }
+
+  public void setEmployees(List<Person> employees) {
+    this.employees = employees;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Tenant tenant = (Tenant)o;
+
+    if (tenantId != null ? !tenantId.equals(tenant.tenantId)
+        : tenant.tenantId != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return (tenantId != null ? tenantId.hashCode() : 0);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Window.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Window.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/model/Window.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,65 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.model;
+
+import java.io.Serializable;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class Window {
+  private Serializable windowId;
+
+  private boolean opens;
+
+  public Serializable getWindowId() {
+    return windowId;
+  }
+
+  public void setWindowId(Serializable windowId) {
+    this.windowId = windowId;
+  }
+
+  public boolean getOpens() {
+    return opens;
+  }
+
+  public void setOpens(boolean opens) {
+    this.opens = opens;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Window window = (Window) o;
+
+    return windowId.equals(window.windowId);
+  }
+
+  @Override
+  public int hashCode() {
+    return windowId.hashCode();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryEventDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryEventDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryEventDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class QueryEventDefaultMock implements QueryEvent {
+
+  public void onEvent(Query query) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/QueryFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class QueryFactoryDefaultMock implements QueryFactory {
+  public Query createQuery(Session session) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigDecimalEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigDecimalEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigDecimalEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.math.BigDecimal;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBigDecimalEventTest extends TestCase {
+
+   public void testSetBigDecimalEventPositionVal() {
+     SetBigDecimalEvent event = new SetBigDecimalEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBigDecimal(int position, BigDecimal val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetBigDecimalEventNameVal() {
+     SetBigDecimalEvent event = new SetBigDecimalEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBigDecimal(String name, BigDecimal val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigIntegerEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigIntegerEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBigIntegerEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.math.BigInteger;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetBigIntegerEventTest extends TestCase {
+
+   public void testSetBigIntegerEventPositionVal() {
+     SetBigIntegerEvent event = new SetBigIntegerEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBigInteger(int position, BigInteger val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetBigIntegerEventNameVal() {
+     SetBigIntegerEvent event = new SetBigIntegerEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBigInteger(String name, BigInteger val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBinaryEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBinaryEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBinaryEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetBinaryEventTest extends TestCase {
+
+   public void testSetBinaryEventPositionVal() {
+     SetBinaryEvent event = new SetBinaryEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBinary(int position, byte[] val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetBinaryEventNameVal() {
+     SetBinaryEvent event = new SetBinaryEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBinary(String name, byte[] val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBooleanEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBooleanEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetBooleanEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetBooleanEventTest extends TestCase {
+
+   public void testSetBooleanEventPositionVal() {
+     SetBooleanEvent event = new SetBooleanEvent(-1, false);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBoolean(int position, boolean val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetBooleanEventNameVal() {
+     SetBooleanEvent event = new SetBooleanEvent(null, false);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setBoolean(String name, boolean val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetByteEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetByteEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetByteEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetByteEventTest extends TestCase {
+
+   public void testSetByteEventPositionVal() {
+     SetByteEvent event = new SetByteEvent(-1, (byte) 0);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setByte(int position, byte val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetByteEventNameVal() {
+     SetByteEvent event = new SetByteEvent(null, (byte) 0);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setByte(String name, byte val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.CacheMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCacheModeEventTest extends TestCase {
+
+   public void testSetCacheModeEventCachemode() {
+     SetCacheModeEvent event = new SetCacheModeEvent(null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCacheMode(CacheMode cacheMode) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheRegionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheRegionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheRegionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetCacheRegionEventTest extends TestCase {
+
+   public void testSetCacheRegionEventCacheregion() {
+     SetCacheRegionEvent event = new SetCacheRegionEvent(null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCacheRegion(String cacheRegion) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheableEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheableEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCacheableEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetCacheableEventTest extends TestCase {
+
+   public void testSetCacheableEventCacheable() {
+     SetCacheableEvent event = new SetCacheableEvent(false);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCacheable(boolean cacheable) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarDateEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarDateEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarDateEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Calendar;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCalendarDateEventTest extends TestCase {
+
+   public void testSetCalendarDateEventPositionVal() {
+     SetCalendarDateEvent event = new SetCalendarDateEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCalendarDate(int position, Calendar val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetCalendarDateEventNameVal() {
+     SetCalendarDateEvent event = new SetCalendarDateEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCalendarDate(String name, Calendar val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCalendarEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Calendar;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetCalendarEventTest extends TestCase {
+
+   public void testSetCalendarEventPositionVal() {
+     SetCalendarEvent event = new SetCalendarEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCalendar(int position, Calendar val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetCalendarEventNameVal() {
+     SetCalendarEvent event = new SetCalendarEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCalendar(String name, Calendar val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCharacterEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCharacterEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCharacterEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetCharacterEventTest extends TestCase {
+
+   public void testSetCharacterEventPositionVal() {
+     SetCharacterEvent event = new SetCharacterEvent(-1, 'a');
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCharacter(int position, char val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetCharacterEventNameVal() {
+     SetCharacterEvent event = new SetCharacterEvent(null, 'a');
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setCharacter(String name, char val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCommentEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCommentEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetCommentEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetCommentEventTest extends TestCase {
+
+   public void testSetCommentEventComment() {
+     SetCommentEvent event = new SetCommentEvent(null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setComment(String comment) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDateEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDateEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDateEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetDateEventTest extends TestCase {
+
+   public void testSetDateEventPositionVal() {
+     SetDateEvent event = new SetDateEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setDate(int position, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetDateEventNameVal() {
+     SetDateEvent event = new SetDateEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setDate(String name, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDoubleEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDoubleEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetDoubleEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetDoubleEventTest extends TestCase {
+
+   public void testSetDoubleEventPositionVal() {
+     SetDoubleEvent event = new SetDoubleEvent(-1, new Double(-1.0));
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setDouble(int position, double val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetDoubleEventNameVal() {
+     SetDoubleEvent event = new SetDoubleEvent(null, new Double(-1.0));
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setDouble(String name, double val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetEntityEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetEntityEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetEntityEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetEntityEventTest extends TestCase {
+
+   public void testSetEntityEventPositionVal() {
+     SetEntityEvent event = new SetEntityEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setEntity(int position, Object val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetEntityEventNameVal() {
+     SetEntityEvent event = new SetEntityEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setEntity(String name, Object val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFetchSizeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFetchSizeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFetchSizeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetFetchSizeEventTest extends TestCase {
+
+   public void testSetFetchSizeEventFetchsize() {
+     SetFetchSizeEvent event = new SetFetchSizeEvent(-1);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setFetchSize(int fetchSize) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFirstResultEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFirstResultEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFirstResultEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Query;
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetFirstResultEventTest extends TestCase {
+
+   public void testSetFirstResultEventFirstresult() {
+     SetFirstResultEvent event = new SetFirstResultEvent(-1);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setFirstResult(int firstResult) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFloatEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFloatEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFloatEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Query;
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetFloatEventTest extends TestCase {
+
+   public void testSetFloatEventPositionVal() {
+     SetFloatEvent event = new SetFloatEvent(-1, 0f);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setFloat(int position, float val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetFloatEventNameVal() {
+     SetFloatEvent event = new SetFloatEvent(null, 0f);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setFloat(String name, float val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFlushModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFlushModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetFlushModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.FlushMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetFlushModeEventTest extends TestCase {
+
+   public void testSetFlushModeEventFlushmode() {
+     SetFlushModeEvent event = new SetFlushModeEvent(null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setFlushMode(FlushMode flushMode) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetIntegerEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetIntegerEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetIntegerEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetIntegerEventTest extends TestCase {
+
+   public void testSetIntegerEventPositionVal() {
+     SetIntegerEvent event = new SetIntegerEvent(-1, new Integer(-1));
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setInteger(int position, int val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetIntegerEventNameVal() {
+     SetIntegerEvent event = new SetIntegerEvent(null, new Integer(-1));
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setInteger(String name, int val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLocaleEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLocaleEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLocaleEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Locale;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetLocaleEventTest extends TestCase {
+
+   public void testSetLocaleEventPositionVal() {
+     SetLocaleEvent event = new SetLocaleEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setLocale(int position, Locale val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetLocaleEventNameVal() {
+     SetLocaleEvent event = new SetLocaleEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setLocale(String name, Locale val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLockModeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLockModeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLockModeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.LockMode;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetLockModeEventTest extends TestCase {
+
+   public void testSetLockModeEventAliasLockmode() {
+     SetLockModeEvent event = new SetLockModeEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setLockMode(String alias, LockMode lockMode) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLongEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLongEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetLongEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetLongEventTest extends TestCase {
+
+   public void testSetLongEventPositionVal() {
+     SetLongEvent event = new SetLongEvent(-1, 0l);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setLong(int position, long val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetLongEventNameVal() {
+     SetLongEvent event = new SetLongEvent(null, 0l);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setLong(String name, long val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetMaxResultsEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetMaxResultsEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetMaxResultsEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetMaxResultsEventTest extends TestCase {
+
+   public void testSetMaxResultsEventMaxresults() {
+     SetMaxResultsEvent event = new SetMaxResultsEvent(-1);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setMaxResults(int maxResults) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,86 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParameterEventTest extends TestCase {
+
+   public void testSetParameterEventPositionValType() {
+     SetParameterEvent event = new SetParameterEvent(-1, null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameter(int position, Object val, Type type) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterEventNameValType() {
+     SetParameterEvent event = new SetParameterEvent(null, null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameter(String name, Object val, Type type) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterEventPositionVal() {
+     SetParameterEvent event = new SetParameterEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameter(int position, Object val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterEventNameVal() {
+     SetParameterEvent event = new SetParameterEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameter(String name, Object val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterListEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterListEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParameterListEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+import java.util.Collection;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParameterListEventTest extends TestCase {
+
+   public void testSetParameterListEventNameValsCollType() {
+     SetParameterListEvent event = new SetParameterListEvent(null, Lists.newArrayList(), null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameterList(String name, Collection vals, Type type) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterListEventNameValsColl() {
+     SetParameterListEvent event = new SetParameterListEvent(null, Lists.newArrayList());
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameterList(String name, Collection vals) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterListEventNameValsArr() {
+     SetParameterListEvent event = new SetParameterListEvent(null, new Object[0]);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameterList(String name, Object[] vals) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetParameterListEventNameValsArrType() {
+     SetParameterListEvent event = new SetParameterListEvent(null, new Object[0], null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameterList(String name, Object[] vals, Type type) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParametersEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParametersEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetParametersEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.type.Type;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetParametersEventTest extends TestCase {
+
+   public void testSetParametersEventValuesTypes() {
+     SetParametersEvent event = new SetParametersEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setParameters(Object[] values, Type[] types) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetPropertiesEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetPropertiesEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetPropertiesEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Map;
+import java.util.Collections;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetPropertiesEventTest extends TestCase {
+
+  public void testSetPropertiesEventBean() {
+    SetPropertiesEvent event = new SetPropertiesEvent(new Object());
+    final boolean[] called = {false};
+    Query query = new QueryDefaultMock() {
+      @Override
+      public Query setProperties(Object bean) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(query);
+    assertTrue(called[0]);
+  }
+
+  public void testSetPropertiesEventMap() {
+    SetPropertiesEvent event = new SetPropertiesEvent(Collections.emptyMap());
+    final boolean[] called = {false};
+    Query query = new QueryDefaultMock() {
+      @Override
+      public Query setProperties(Map map) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onEvent(query);
+    assertTrue(called[0]);
+  }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetReadOnlyEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetReadOnlyEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetReadOnlyEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetReadOnlyEventTest extends TestCase {
+
+   public void testSetReadOnlyEventReadonly() {
+     SetReadOnlyEvent event = new SetReadOnlyEvent(false);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setReadOnly(boolean readOnly) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetResultTransformerEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetResultTransformerEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetResultTransformerEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+import org.hibernate.transform.ResultTransformer;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetResultTransformerEventTest extends TestCase {
+
+   public void testSetResultTransformerEventTransformer() {
+     SetResultTransformerEvent event = new SetResultTransformerEvent(null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setResultTransformer(ResultTransformer transformer) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetSerializableEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetSerializableEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetSerializableEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,59 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.io.Serializable;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetSerializableEventTest extends TestCase {
+
+   public void testSetSerializableEventPositionVal() {
+     SetSerializableEvent event = new SetSerializableEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setSerializable(int position, Serializable val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetSerializableEventNameVal() {
+     SetSerializableEvent event = new SetSerializableEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setSerializable(String name, Serializable val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetShortEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetShortEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetShortEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetShortEventTest extends TestCase {
+
+   public void testSetShortEventPositionVal() {
+     SetShortEvent event = new SetShortEvent(-1, (short) 0);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setShort(int position, short val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetShortEventNameVal() {
+     SetShortEvent event = new SetShortEvent(null, (short) 0);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setShort(String name, short val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetStringEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetStringEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetStringEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetStringEventTest extends TestCase {
+
+   public void testSetStringEventPositionVal() {
+     SetStringEvent event = new SetStringEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setString(int position, String val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetStringEventNameVal() {
+     SetStringEvent event = new SetStringEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setString(String name, String val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTextEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTextEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTextEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetTextEventTest extends TestCase {
+
+   public void testSetTextEventPositionVal() {
+     SetTextEvent event = new SetTextEvent(-1, "");
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setText(int position, String val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetTextEventNameVal() {
+     SetTextEvent event = new SetTextEvent(null, "");
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setText(String name, String val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTimeEventTest extends TestCase {
+
+   public void testSetTimeEventPositionVal() {
+     SetTimeEvent event = new SetTimeEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setTime(int position, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetTimeEventNameVal() {
+     SetTimeEvent event = new SetTimeEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setTime(String name, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeoutEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeoutEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimeoutEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,42 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+import junit.framework.TestCase;
+import org.hibernate.Query;
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+ public class SetTimeoutEventTest extends TestCase {
+
+   public void testSetTimeoutEventTimeout() {
+     SetTimeoutEvent event = new SetTimeoutEvent(-1);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setTimeout(int timeout) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimestampEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimestampEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/SetTimestampEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.shards.defaultmock.QueryDefaultMock;
+
+import junit.framework.TestCase;
+import org.hibernate.Query;
+
+import java.util.Date;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class SetTimestampEventTest extends TestCase {
+
+   public void testSetTimestampEventPositionVal() {
+     SetTimestampEvent event = new SetTimestampEvent(-1, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setTimestamp(int position, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+
+   public void testSetTimestampEventNameVal() {
+     SetTimestampEvent event = new SetTimestampEvent(null, null);
+     final boolean[] called = {false};
+     Query query = new QueryDefaultMock() {
+       @Override
+       public Query setTimestamp(String name, Date val) {
+         called[0] = true;
+         return null;
+       }
+     };
+     event.onEvent(query);
+     assertTrue(called[0]);
+   }
+}
\ No newline at end of file

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/ShardedQueryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/ShardedQueryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/query/ShardedQueryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,341 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.query;
+
+import org.hibernate.type.Type;
+import org.hibernate.*;
+import org.hibernate.transform.ResultTransformer;
+
+import java.util.*;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ShardedQueryDefaultMock implements ShardedQuery {
+  public QueryId getQueryId() {
+    throw new UnsupportedOperationException();
+  }
+
+  public QueryFactory getQueryFactory() {
+    throw new UnsupportedOperationException();
+  }
+
+  public String getQueryString() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Type[] getReturnTypes() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getReturnAliases() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public String[] getNamedParameters() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Iterator iterate() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public List list() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Object uniqueResult() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public int executeUpdate() throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setMaxResults(int maxResults) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFirstResult(int firstResult) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setReadOnly(boolean readOnly) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheable(boolean cacheable) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheRegion(String cacheRegion) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimeout(int timeout) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFetchSize(int fetchSize) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLockMode(String alias, LockMode lockMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setComment(String comment) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFlushMode(FlushMode flushMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCacheMode(CacheMode cacheMode) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(int position, Object val, Type type) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(String name, Object val, Type type) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(int position, Object val) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameter(String name, Object val) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameters(Object[] values, Type[] types) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Collection vals) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Object[] vals, Type type) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setParameterList(String name, Object[] vals) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setProperties(Object bean) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setString(int position, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCharacter(int position, char val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBoolean(int position, boolean val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setByte(int position, byte val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setShort(int position, short val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setInteger(int position, int val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLong(int position, long val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFloat(int position, float val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDouble(int position, double val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBinary(int position, byte[] val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setText(int position, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setSerializable(int position, Serializable val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLocale(int position, Locale locale) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigDecimal(int position, BigDecimal number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigInteger(int position, BigInteger number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDate(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTime(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimestamp(int position, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendar(int position, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendarDate(int position, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setString(String name, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCharacter(String name, char val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBoolean(String name, boolean val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setByte(String name, byte val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setShort(String name, short val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setInteger(String name, int val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLong(String name, long val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setFloat(String name, float val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDouble(String name, double val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBinary(String name, byte[] val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setText(String name, String val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setSerializable(String name, Serializable val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setLocale(String name, Locale locale) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigDecimal(String name, BigDecimal number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setBigInteger(String name, BigInteger number) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setDate(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTime(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setTimestamp(String name, Date date) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendar(String name, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setCalendarDate(String name, Calendar calendar) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setEntity(int position, Object val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setEntity(String name, Object val) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setResultTransformer(ResultTransformer transformer) {
+    throw new UnsupportedOperationException();
+  }
+
+  public Query setProperties(Map bean) throws HibernateException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecoratorTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecoratorTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorDecoratorTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.InterceptorDefaultMock;
+import org.hibernate.shards.ShardId;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Interceptor;
+import org.hibernate.CallbackException;
+import org.hibernate.type.Type;
+
+import java.io.Serializable;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class CrossShardRelationshipDetectingInterceptorDecoratorTest extends TestCase {
+
+  public void testOnFlushDirty() {
+    final boolean[] onFlushDirtyCalled = {false, false};
+    Interceptor interceptor = new InterceptorDefaultMock() {
+      @Override
+      public boolean onFlushDirty(Object entity, Serializable id,
+          Object[] currentState, Object[] previousState, String[] propertyNames,
+          Type[] types) throws CallbackException {
+        onFlushDirtyCalled[0] = true;
+        return true;
+      }
+    };
+    ShardId shardId = new ShardId(0);
+    ShardIdResolver resolver = new ShardIdResolverDefaultMock();
+
+    CrossShardRelationshipDetectingInterceptor crdi = new CrossShardRelationshipDetectingInterceptor(resolver) {
+      @Override
+      public boolean onFlushDirty(Object entity, Serializable id,
+          Object[] currentState, Object[] previousState, String[] propertyNames,
+          Type[] types) throws CallbackException {
+        onFlushDirtyCalled[1] = true;
+        return false;
+      }
+    };
+    CrossShardRelationshipDetectingInterceptorDecorator decorator =
+        new CrossShardRelationshipDetectingInterceptorDecorator(crdi, interceptor);
+
+    assertTrue(decorator.onFlushDirty(null, null, null, null, null, null));
+    assertTrue(onFlushDirtyCalled[0]);
+    assertTrue(onFlushDirtyCalled[1]);
+  }
+
+  public void testOnCollectionUpdate() {
+    final boolean[] onCollectionUpdateCalled = {false, false};
+    Interceptor interceptor = new InterceptorDefaultMock() {
+      @Override
+      public void onCollectionUpdate(Object collection, Serializable key)
+          throws CallbackException {
+        onCollectionUpdateCalled[0] = true;
+      }
+    };
+    ShardId shardId = new ShardId(0);
+    ShardIdResolver resolver = new ShardIdResolverDefaultMock();
+
+    CrossShardRelationshipDetectingInterceptor crdi = new CrossShardRelationshipDetectingInterceptor(resolver) {
+      @Override
+      public void onCollectionUpdate(Object collection, Serializable key)
+          throws CallbackException {
+        onCollectionUpdateCalled[1] = true;
+      }
+    };
+    CrossShardRelationshipDetectingInterceptorDecorator decorator =
+        new CrossShardRelationshipDetectingInterceptorDecorator(crdi, interceptor);
+
+    decorator.onCollectionUpdate(null, null);
+    assertTrue(onCollectionUpdateCalled[0]);
+    assertTrue(onCollectionUpdateCalled[1]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptorTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.TypeDefaultMock;
+import org.hibernate.shards.CrossShardAssociationException;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Pair;
+
+import junit.framework.TestCase;
+
+import org.hibernate.type.Type;
+
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class CrossShardRelationshipDetectingInterceptorTest extends TestCase {
+
+  public void testCheckForConflictingShardId() {
+    ShardId shardId = new ShardId(0);
+    final ShardId[] shardIdToReturn = {null};
+    ShardIdResolver resolver = new ShardIdResolverDefaultMock() {
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdToReturn[0];
+      }
+    };
+    CrossShardRelationshipDetectingInterceptor crdi = new CrossShardRelationshipDetectingInterceptor(resolver);
+    Object obj = new Object();
+    crdi.checkForConflictingShardId("yam", shardId, obj);
+    shardIdToReturn[0] = shardId;
+    crdi.checkForConflictingShardId("yam", shardId, obj);
+    shardIdToReturn[0] = new ShardId(1);
+    try {
+      crdi.checkForConflictingShardId("yam", shardId, obj);
+      fail("Expected Cross Shard Association Exception");
+    } catch (CrossShardAssociationException csae) {
+      // good
+    }
+  }
+
+  private static final class MyType extends TypeDefaultMock {
+
+    private final boolean isAssociationType;
+
+    public MyType(boolean associationType) {
+      isAssociationType = associationType;
+    }
+
+    @Override
+    public boolean isAssociationType() {
+      return isAssociationType;
+    }
+  }
+
+  public void testAssociationPairFilter() {
+    Pair<Type, Object> expectedPair = Pair.<Type, Object>of(new MyType(true), "yam");
+    Type[] types = {new MyType(false), new MyType(true), new MyType(false), expectedPair.first};
+    Object[] objects = {null, null, "yam", expectedPair.second};
+    List<Pair<Type, Object>> list = CrossShardRelationshipDetectingInterceptor.buildListOfAssociations(types, objects);
+    assertEquals(1, list.size());
+    Pair<Type, Object> pair = list.get(0);
+    assertNotNull(pair);
+    assertEquals(expectedPair, pair);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/DisableFilterOpenSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/DisableFilterOpenSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/DisableFilterOpenSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,44 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class DisableFilterOpenSessionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    DisableFilterOpenSessionEvent event = new DisableFilterOpenSessionEvent("yam");
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public void disableFilter(String filterName) {
+        called[0] = true;
+      }
+    };
+    event.onOpenSession(session);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/EnableFilterOpenSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/EnableFilterOpenSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/EnableFilterOpenSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+import org.hibernate.Filter;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class EnableFilterOpenSessionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    EnableFilterOpenSessionEvent event = new EnableFilterOpenSessionEvent("yam");
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public Filter enableFilter(String filterName) {
+        called[0] = true;
+        return null;
+      }
+    };
+    event.onOpenSession(session);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/OpenSessionEventDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/OpenSessionEventDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/OpenSessionEventDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class OpenSessionEventDefaultMock implements OpenSessionEvent {
+
+  public void onOpenSession(Session session) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetCacheModeOpenSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetCacheModeOpenSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetCacheModeOpenSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetCacheModeOpenSessionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetCacheModeOpenSessionEvent event = new SetCacheModeOpenSessionEvent(CacheMode.IGNORE);
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public void setCacheMode(CacheMode cacheMode) {
+        called[0] = true;
+      }
+    };
+    event.onOpenSession(session);
+    assertTrue(called[0]);
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetFlushModeOpenSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetFlushModeOpenSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetFlushModeOpenSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.FlushMode;
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetFlushModeOpenSessionEventTest extends TestCase {
+  public void testOnOpenSession() {
+    SetFlushModeOpenSessionEvent event = new SetFlushModeOpenSessionEvent(FlushMode.ALWAYS);
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public void setFlushMode(FlushMode flushMode) {
+        called[0] = true;
+      }
+    };
+    event.onOpenSession(session);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetReadOnlyOpenSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetReadOnlyOpenSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetReadOnlyOpenSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetReadOnlyOpenSessionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    SetReadOnlyOpenSessionEvent event = new SetReadOnlyOpenSessionEvent(null, false);
+    final boolean[] called = {false};
+    Session session = new SessionDefaultMock() {
+      @Override
+      public void setReadOnly(Object entity, boolean readOnly) {
+        called[0] = true;
+      }
+    };
+    event.onOpenSession(session);
+    assertTrue(called[0]);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetSessionOnRequiresSessionEventTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetSessionOnRequiresSessionEventTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/SetSessionOnRequiresSessionEventTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class SetSessionOnRequiresSessionEventTest extends TestCase {
+
+  public void testOnOpenSession() {
+    class MyRequiresSession implements RequiresSession {
+      private Session session;
+      public void setSession(Session session) {
+        this.session = session;
+      }
+    }
+    MyRequiresSession requiresSession = new MyRequiresSession();
+    SetSessionOnRequiresSessionEvent event = new SetSessionOnRequiresSessionEvent(requiresSession);
+    Session session = new SessionDefaultMock();
+    event.onOpenSession(session);
+    assertSame(requiresSession.session, session);
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardIdResolverDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardIdResolverDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardIdResolverDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.Shard;
+
+import java.util.List;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+class ShardIdResolverDefaultMock implements ShardIdResolver {
+
+  public ShardId getShardIdForObject(Object obj, List<Shard> shardsToConsider) {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardId getShardIdForObject(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionFactoryImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionFactoryImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionFactoryImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,388 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyDefaultMock;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.strategy.ShardStrategyFactoryDefaultMock;
+import org.hibernate.shards.session.ShardedSessionFactoryImpl;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Sets;
+import org.hibernate.shards.session.ShardedSessionFactory;
+
+import junit.framework.TestCase;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.NamingException;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionFactoryImplTest extends TestCase {
+  private SessionFactoryImplementor sf;
+  private ShardId shardId;
+
+  @Override
+  protected void setUp() {
+    sf = new SessionFactoryDefaultMock() {
+      @Override
+      public Settings getSettings() {
+        Configuration config = new Configuration();
+        Properties prop = new Properties();
+        prop.setProperty(Environment.SESSION_FACTORY_NAME, "1");
+        prop.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLInnoDBDialect");
+        return config.buildSettings(prop);
+      }
+
+      @Override
+      public void close() throws HibernateException {
+      }
+
+      @Override
+      public Map getAllClassMetadata() throws HibernateException {
+        return Collections.emptyMap();
+      }
+    };
+    shardId = new ShardId(1);
+  }
+
+  private ShardStrategyFactory buildStrategyFactoryDefaultMock() {
+    return new ShardStrategyFactoryDefaultMock() {
+      @Override
+      public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+        return new ShardStrategyDefaultMock();
+      }
+    };
+  }
+
+  public void testCtors() {
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    Set<Class<?>> crsl = Collections.emptySet();
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    try {
+      new ShardedSessionFactoryImpl(null, shardStrategyFactory, crsl, false);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    try {
+      new ShardedSessionFactoryImpl(sfMap, null, crsl, false);
+      fail("expected iae");
+    } catch (IllegalArgumentException iae) {
+      // good
+    }
+
+    sfMap.put(this.sf, Sets.newHashSet(shardId));
+    try {
+      new ShardedSessionFactoryImpl(sfMap, null, crsl, false);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    try {
+      new ShardedSessionFactoryImpl(sfMap, shardStrategyFactory, null, false);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+
+    ShardedSessionFactoryImpl ssfi = new ShardedSessionFactoryImpl(sfMap, shardStrategyFactory, crsl, false);
+    ssfi.close();
+  }
+
+  public void testOpenSessionWithUserSuppliedConnection() {
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    ShardedSessionFactory ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    try {
+      Connection conn = null;
+      try {
+        ssf.openSession(conn);
+        fail("Expected uoe");
+      } catch (UnsupportedOperationException uoe) {
+        // good
+      }
+      Interceptor interceptor = null;
+      try {
+        ssf.openSession(conn, interceptor);
+        fail("Expected uoe");
+      } catch (UnsupportedOperationException uoe) {
+        // good
+      }
+    } finally {
+      ssf.close();
+    }
+  }
+
+  public void testOpenStatelessSessionWithUserSuppliedConnection() {
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    ShardedSessionFactory ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    try {
+      Connection conn = null;
+      try {
+        ssf.openStatelessSession(conn);
+        fail("Expected uoe");
+      } catch (UnsupportedOperationException uoe) {
+        // good
+      }
+    } finally {
+      ssf.close();
+    }
+  }
+
+  public void testIsClosed() {
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+
+    SessionFactoryDefaultMock mock1 = new SessionFactoryDefaultMock() {
+
+      @Override
+      public boolean isClosed() {
+        return false;
+      }
+
+      @Override
+      public Settings getSettings() {
+        Configuration config = new Configuration();
+        Properties prop = new Properties();
+        prop.setProperty(Environment.SESSION_FACTORY_NAME, "1");
+        prop.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLInnoDBDialect");
+        return config.buildSettings(prop);
+      }
+
+      @Override
+      public void close() throws HibernateException {
+      }
+
+      @Override
+      public Map getAllClassMetadata() throws HibernateException {
+        return Collections.emptyMap();
+      }
+    };
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(mock1, Sets.newHashSet(new ShardId(1)));
+    ShardedSessionFactory ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    try {
+      assertFalse(ssf.isClosed());
+    } finally {
+      ssf.close();
+    }
+    SessionFactoryDefaultMock mock2 = new SessionFactoryDefaultMock() {
+
+      @Override
+      public boolean isClosed() {
+        return true;
+      }
+
+      @Override
+      public Settings getSettings() {
+        Configuration config = new Configuration();
+        Properties prop = new Properties();
+        prop.setProperty(Environment.SESSION_FACTORY_NAME, "2");
+        prop.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLInnoDBDialect");
+        return config.buildSettings(prop);
+      }
+
+      @Override
+      public void close() throws HibernateException {
+      }
+
+      @Override
+      public Map getAllClassMetadata() throws HibernateException {
+        return Collections.emptyMap();
+      }
+    };
+    sfMap.put(mock2, Sets.newHashSet(new ShardId(2)));
+    ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    try {
+      assertTrue(ssf.isClosed());
+    } finally {
+      ssf.close();
+    }
+  }
+
+  public void testGetReference() throws NamingException {
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    ShardedSessionFactory ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    try {
+      ssf.getReference();
+      fail("Expected uoe");
+    } catch (UnsupportedOperationException uoe) {
+      // good
+    } finally {
+      ssf.close();
+    }
+  }
+
+  public void testGetStatistics() {
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    ShardedSessionFactory ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false);
+    assertNotNull(ssf.getStatistics());
+  }
+
+  public void testFinalizeOnOpenSession() throws Throwable {
+
+    final boolean[] closeCalled = {false};
+
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    ShardedSessionFactoryImpl ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false) {
+          @Override
+          public void close() throws HibernateException {
+            closeCalled[0] = true;
+            super.close();
+          }
+
+          @Override
+          public boolean isClosed() {
+            return false;
+          }
+        };
+    ssf.finalize();
+    assertTrue(closeCalled[0]);
+  }
+
+  public void testFinalizeOnClosedSession() throws Throwable {
+    final boolean[] closeCalled = {false};
+
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+    ShardedSessionFactoryImpl ssf =
+        new ShardedSessionFactoryImpl(
+            sfMap,
+            shardStrategyFactory,
+            Collections.<Class<?>>emptySet(),
+            false) {
+          @Override
+          public void close() throws HibernateException {
+            closeCalled[0] = true;
+            super.close();
+          }
+
+          @Override
+          public boolean isClosed() {
+            return true;
+          }
+        };
+    ssf.finalize();
+    assertFalse(closeCalled[0]);
+  }
+
+  public void testFailsWhenMultipleSessionFactoriesHaveSameShardId() {
+    Map<SessionFactoryImplementor, Set<ShardId>> sfMap = Maps.newHashMap();
+    Set<Class<?>> crsl = Collections.emptySet();
+    ShardStrategyFactory shardStrategyFactory = buildStrategyFactoryDefaultMock();
+    sfMap.put(sf, Sets.newHashSet(shardId));
+
+    SessionFactoryImplementor sf2 = new SessionFactoryDefaultMock() {
+      @Override
+      public Settings getSettings() {
+        Configuration config = new Configuration();
+        Properties prop = new Properties();
+        prop.setProperty(Environment.SESSION_FACTORY_NAME, "1");
+        prop.setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLInnoDBDialect");
+        return config.buildSettings(prop);
+      }
+
+      @Override
+      public void close() throws HibernateException {
+      }
+
+      @Override
+      public Map getAllClassMetadata() throws HibernateException {
+        return Collections.emptyMap();
+      }
+    };
+
+    sfMap.put(sf2, Sets.newHashSet(new ShardId(1)));
+
+    try {
+      new ShardedSessionFactoryImpl(sfMap, shardStrategyFactory, crsl, false);
+      fail("expected hibernate exception");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/session/ShardedSessionImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,649 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.session;
+
+import org.hibernate.shards.defaultmock.ClassMetadataDefaultMock;
+import org.hibernate.shards.defaultmock.InterceptorDefaultMock;
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.defaultmock.TypeDefaultMock;
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardDefaultMock;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.ShardImpl;
+import org.hibernate.shards.ShardedSessionFactoryDefaultMock;
+import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyDefaultMock;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategyDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Maps;
+import org.hibernate.shards.util.Pair;
+import org.hibernate.shards.util.Sets;
+
+import junit.framework.TestCase;
+
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.hibernate.Interceptor;
+import org.hibernate.Session;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.type.Type;
+
+import java.sql.Connection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardedSessionImplTest extends TestCase {
+
+  private static class MyShardedSessionImpl extends ShardedSessionImpl {
+
+    public MyShardedSessionImpl() {
+      super(
+          new ShardedSessionFactoryDefaultMock() {
+            @Override
+            public Map<SessionFactoryImplementor, Set<ShardId>> getSessionFactoryShardIdMap() {
+              return Collections.emptyMap();
+            }
+          },
+          new ShardStrategyDefaultMock(),
+          Collections.<Class<?>>emptySet(),
+          true);
+    }
+  }
+
+  public void testApplySaveOrUpdateOperation() {
+    final List[] listToReturn = { Lists.newArrayList(new ShardId(0)) };
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      @Override
+      List<ShardId> determineShardIdsForObjectThatMightAlreadyExist(Object object) {
+        return listToReturn[0];
+      }
+    };
+
+    final boolean[] saveOrUpdateCalled = { false };
+    final boolean[] updateCalled = { false };
+    ShardedSessionImpl.SaveOrUpdateOperation op = new ShardedSessionImpl.SaveOrUpdateOperation() {
+      public void saveOrUpdate(Shard shard, Object object) {
+        saveOrUpdateCalled[0] = true;
+      }
+
+      public void update(Shard shard, Object object) {
+        updateCalled[0] = true;
+      }
+    };
+    ssi.applySaveOrUpdateOperation(op, null);
+    assertTrue(saveOrUpdateCalled[0]);
+    assertFalse(updateCalled[0]);
+
+    saveOrUpdateCalled[0] = false;
+    listToReturn[0].add(new ShardDefaultMock());
+
+    ssi.applySaveOrUpdateOperation(op, null);
+    assertFalse(saveOrUpdateCalled[0]);
+    assertTrue(updateCalled[0]);
+  }
+
+  public void testClose() {
+    ShardedSessionImpl ssi = new MyShardedSessionImpl();
+    ssi.close();
+  }
+
+  public void testShardLock() {
+    final ShardId shardIdToReturn = new ShardId(0);
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      private boolean called = false;
+      @Override
+      ShardId getShardIdOfRelatedObject(Object obj) {
+        if(called) {
+          throw new UnsupportedOperationException();
+        }
+        called = true;
+        return shardIdToReturn;
+      }
+    };
+    ssi.lockShard();
+    Object obj = new Object();
+    assertSame(shardIdToReturn, ssi.selectShardIdForNewObject(obj));
+    assertSame(shardIdToReturn, ssi.selectShardIdForNewObject(obj));
+  }
+
+  public void testLackingShardLock() {
+    ShardedSessionFactoryImplementor ssf = new ShardedSessionFactoryDefaultMock() {
+      @Override
+      public Map<SessionFactoryImplementor, Set<ShardId>> getSessionFactoryShardIdMap() {
+        return Collections.emptyMap();
+      }
+    };
+
+    final ShardId shardIdToReturn = new ShardId(33);
+    final ShardSelectionStrategy shardSelectionStrategy = new ShardSelectionStrategyDefaultMock() {
+      @Override
+      public ShardId selectShardIdForNewObject(Object obj) {
+        return shardIdToReturn;
+      }
+    };
+    ShardStrategy shardStrategy = new ShardStrategyDefaultMock() {
+      @Override
+      public ShardSelectionStrategy getShardSelectionStrategy() {
+        return shardSelectionStrategy;
+      }
+    };
+    Set<Class<?>> classesRequiringShardLocks =
+        Sets.<Class<?>>newHashSet(Integer.class, String.class);
+    ShardedSessionImpl ssi =
+        new ShardedSessionImpl(ssf, shardStrategy, classesRequiringShardLocks, true) {
+      @Override
+      ShardId getShardIdOfRelatedObject(Object obj) {
+        return null;
+      }
+    };
+    assertSame(shardIdToReturn, ssi.selectShardIdForNewObject(new Object()));
+    try {
+      ssi.selectShardIdForNewObject(3);
+      fail("expected he");
+    } catch (HibernateException he) {
+      // good
+    }
+    try {
+    ssi.selectShardIdForNewObject("three");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testGetShardIdOfRelatedObjectWithNullAssociation() {
+    // the mapping has an association, but the value for that association is null
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(33)};
+      int shardIdForObjectToReturnIndex = 0;
+
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, false), new MyType(true, false)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {null, null};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test an association
+    assertNull(ssi.getShardIdOfRelatedObject(obj));
+  }
+
+  public void testGetShardIdOfRelatedObjectWithAssociation() {
+    // the mapping has an assocation and the association is not null
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(33)};
+      int shardIdForObjectToReturnIndex = 0;
+
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, false), new MyType(true, false)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {"yam", "jam"};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test an association
+    assertEquals(new ShardId(33), ssi.getShardIdOfRelatedObject(obj));
+  }
+
+  public void testGetShardIdOfRelatedObjectWithBadAssociation() {
+    // the mapping has an association that is not null, and the shard id
+    // for that assocation does not match
+    final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(34)};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      int shardIdForObjectToReturnIndex = 0;
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, false), new MyType(true, false)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {"yam", "jam"};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test a bad association (objects split across multiple shards)
+    try {
+      ssi.getShardIdOfRelatedObject(obj);
+      fail("expecte he");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testGetShardIdOfRelatedObjectWithNullCollection() {
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(33)};
+      int shardIdForObjectToReturnIndex = 0;
+
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(false, false), new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {null, null};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test a collection
+    assertNull(ssi.getShardIdOfRelatedObject(obj));
+  }
+
+  public void testGetShardIdOfRelatedObjectWithCollection() {
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(33)};
+      int shardIdForObjectToReturnIndex = 0;
+
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(false, false), new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {null, Collections.singletonList("yam")};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+
+    // test a collection
+    assertEquals(new ShardId(33), ssi.getShardIdOfRelatedObject(obj));
+  }
+
+  public void testGetShardIdOfRelatedObjectWithBadCollection() {
+    final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(34)};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      int shardIdForObjectToReturnIndex = 0;
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {Lists.newArrayList("jam", "yam")};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test a bad association (objects split across multiple shards)
+    try {
+      ssi.getShardIdOfRelatedObject(obj);
+      fail("expecte he");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testGetShardIdOfRelatedObjectWithBadCollections() {
+    final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(34)};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      int shardIdForObjectToReturnIndex = 0;
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, true), new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {Collections.singletonList("jam"), Collections.singletonList("yam")};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test a bad association (objects split across multiple shards)
+    try {
+      ssi.getShardIdOfRelatedObject(obj);
+      fail("expecte he");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testGetShardIdOfRelatedObjectWithAssociationAndCollection() {
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(33)};
+      int shardIdForObjectToReturnIndex = 0;
+
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, false), new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {"jam", Collections.singletonList("yam")};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+
+    // test a collection
+    assertEquals(new ShardId(33), ssi.getShardIdOfRelatedObject(obj));
+  }
+
+  public void testGetShardIdOfRelatedObjectWithBadAssociationCollection() {
+    final ShardId[] shardIdForObjectToReturn = {new ShardId(33), new ShardId(34)};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      int shardIdForObjectToReturnIndex = 0;
+      @Override
+      ClassMetadata getClassMetadata(Class<?> clazz) {
+        return new ClassMetadataDefaultMock() {
+          @Override
+          public Type[] getPropertyTypes() {
+            return new Type[] {new MyType(true, false), new MyType(true, true)};
+          }
+
+          @Override
+          public Object[] getPropertyValues(Object entity, EntityMode entityMode) {
+            return new Object[] {"yam", Collections.singletonList("jam")};
+          }
+        };
+      }
+
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdForObjectToReturn[shardIdForObjectToReturnIndex++];
+      }
+    };
+
+    Object obj = new Object();
+    // test a bad association (objects split across multiple shards)
+    try {
+      ssi.getShardIdOfRelatedObject(obj);
+      fail("expecte he");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testCheckForConflictingShardId() {
+    final ShardId[] shardIdToReturn = new ShardId[1];
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      @Override
+      public ShardId getShardIdForObject(Object obj) {
+        return shardIdToReturn[0];
+      }
+    };
+    Object obj = new Object();
+    assertNull(ssi.checkForConflictingShardId(null, Object.class, obj));
+    ShardId shardId = new ShardId(0);
+    shardIdToReturn[0] = shardId;
+    assertSame(shardId, ssi.checkForConflictingShardId(null, Object.class, obj));
+    assertSame(shardId, ssi.checkForConflictingShardId(shardId, Object.class, obj));
+    ShardId anotherShardId = new ShardId(1);
+    try {
+      ssi.checkForConflictingShardId(anotherShardId, Object.class, obj);
+      fail("expected he");
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testBuildShardListFromSessionFactoryShardIdMap() {
+    Map<SessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap = Maps.newHashMap();
+    ShardIdResolver resolver = new ShardIdResolverDefaultMock();
+
+    assertTrue(ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, false, resolver, null).isEmpty());
+    assertTrue(ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, true, resolver, null).isEmpty());
+
+    Interceptor interceptor = new InterceptorDefaultMock();
+    assertTrue(ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, false, resolver, interceptor).isEmpty());
+    assertTrue(ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, true, resolver, interceptor).isEmpty());
+
+    sessionFactoryShardIdMap.put(new SessionFactoryDefaultMock(), Sets.newHashSet(new ShardId(0)));
+    sessionFactoryShardIdMap.put(new SessionFactoryDefaultMock(), Sets.newHashSet(new ShardId(1)));
+
+    List<Shard> shards = ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, false, resolver, null);
+    assertEquals(2, shards.size());
+    for(Shard shard : shards) {
+      assertNull(((ShardImpl)shard).getInterceptor());
+    }
+
+    shards = ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, false, resolver, interceptor);
+    assertEquals(2, shards.size());
+    for(Shard shard : shards) {
+      assertSame(interceptor, ((ShardImpl)shard).getInterceptor());
+    }
+
+    shards = ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, true, resolver, null);
+    assertEquals(2, shards.size());
+    for(Shard shard : shards) {
+      assertTrue(((ShardImpl)shard).getInterceptor() instanceof CrossShardRelationshipDetectingInterceptor);
+    }
+
+    shards = ShardedSessionImpl.buildShardListFromSessionFactoryShardIdMap(sessionFactoryShardIdMap, true, resolver, interceptor);
+    assertEquals(2, shards.size());
+    for(Shard shard : shards) {
+      assertTrue(((ShardImpl)shard).getInterceptor() instanceof CrossShardRelationshipDetectingInterceptorDecorator);
+    }
+  }
+
+  public void testFinalizeOnOpenSession() throws Throwable {
+    final boolean[] closeCalled = {false};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      @Override
+      public Connection close() throws HibernateException {
+        closeCalled[0] = true;
+        return super.close();
+      }
+    };
+    ssi.finalize();
+    assertTrue(closeCalled[0]);
+  }
+
+  public void testFinalizeOnClosedSession() throws Throwable {
+    final boolean[] closeCalled = {false};
+    ShardedSessionImpl ssi = new MyShardedSessionImpl() {
+      @Override
+      public Connection close() throws HibernateException {
+        closeCalled[0] = true;
+        return super.close();
+      }
+    };
+    ssi.close();
+    assertTrue(closeCalled[0]);
+    closeCalled[0] = false;
+    ssi.finalize();
+    assertFalse(closeCalled[0]);
+  }
+
+  public void testNonStatefulInterceptorWrapping() {
+    CrossShardRelationshipDetectingInterceptor csrdi =
+        new CrossShardRelationshipDetectingInterceptor(new ShardIdResolverDefaultMock());
+    Interceptor stateless = new InterceptorDefaultMock();
+    Pair<Interceptor, OpenSessionEvent> result = ShardedSessionImpl.decorateInterceptor(csrdi, stateless);
+    assertTrue(result.first instanceof CrossShardRelationshipDetectingInterceptorDecorator);
+    assertSame(csrdi, ((CrossShardRelationshipDetectingInterceptorDecorator)result.first).getCrossShardRelationshipDetectingInterceptor());
+    CrossShardRelationshipDetectingInterceptorDecorator csrdid = (CrossShardRelationshipDetectingInterceptorDecorator) result.first;
+    assertSame(csrdi, csrdid.getCrossShardRelationshipDetectingInterceptor());
+    assertSame(stateless, csrdid.getDelegate());
+    assertNull(result.second);
+  }
+
+  private static class Factory extends InterceptorDefaultMock implements StatefulInterceptorFactory {
+    private final Interceptor interceptorToReturn;
+
+
+    public Factory(Interceptor interceptorToReturn) {
+      this.interceptorToReturn = interceptorToReturn;
+    }
+
+    public Interceptor newInstance() {
+      return interceptorToReturn;
+    }
+  }
+
+  public void testStatefulInterceptorWrapping() {
+    CrossShardRelationshipDetectingInterceptor csrdi =
+        new CrossShardRelationshipDetectingInterceptor(new ShardIdResolverDefaultMock());
+    Interceptor interceptorToReturn = new InterceptorDefaultMock();
+    Interceptor factory = new Factory(interceptorToReturn);
+    Pair<Interceptor, OpenSessionEvent> result = ShardedSessionImpl.decorateInterceptor(csrdi, factory);
+    assertTrue(result.first instanceof CrossShardRelationshipDetectingInterceptorDecorator);
+    assertSame(csrdi, ((CrossShardRelationshipDetectingInterceptorDecorator)result.first).getCrossShardRelationshipDetectingInterceptor());
+    CrossShardRelationshipDetectingInterceptorDecorator csrdid = (CrossShardRelationshipDetectingInterceptorDecorator) result.first;
+    assertSame(csrdi, csrdid.getCrossShardRelationshipDetectingInterceptor());
+    assertSame(interceptorToReturn, csrdid.getDelegate());
+    assertNull(result.second);
+  }
+
+  public void testStatefulInterceptorWrappingWithRequiresSession() {
+    CrossShardRelationshipDetectingInterceptor csrdi =
+        new CrossShardRelationshipDetectingInterceptor(new ShardIdResolverDefaultMock());
+    class RequiresSessionInterceptor extends InterceptorDefaultMock implements RequiresSession {
+      Session setSessionCalledWith;
+      public void setSession(Session session) {
+        this.setSessionCalledWith = session;
+      }
+    }
+    Interceptor interceptorToReturn = new RequiresSessionInterceptor();
+    Interceptor factory = new Factory(interceptorToReturn);
+    Pair<Interceptor, OpenSessionEvent> result = ShardedSessionImpl.decorateInterceptor(csrdi, factory);
+    assertTrue(result.first instanceof CrossShardRelationshipDetectingInterceptorDecorator);
+    assertSame(csrdi, ((CrossShardRelationshipDetectingInterceptorDecorator)result.first).getCrossShardRelationshipDetectingInterceptor());
+    CrossShardRelationshipDetectingInterceptorDecorator csrdid = (CrossShardRelationshipDetectingInterceptorDecorator) result.first;
+    assertSame(csrdi, csrdid.getCrossShardRelationshipDetectingInterceptor());
+    assertSame(interceptorToReturn, csrdid.getDelegate());
+    assertNotNull(result.second);
+  }
+
+  private static final class MyType extends TypeDefaultMock {
+    private final boolean isAssociation;
+    private final boolean isCollection;
+
+    public MyType(boolean association, boolean collection) {
+      isAssociation = association;
+      isCollection = collection;
+    }
+
+    @Override
+    public boolean isAssociationType() {
+      return isAssociation;
+    }
+
+    @Override
+    public boolean isCollectionType() {
+      return isCollection;
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy;
+
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardStrategyDefaultMock implements ShardStrategy {
+
+  public ShardSelectionStrategy getShardSelectionStrategy() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardAccessStrategy getShardAccessStrategy() {
+    throw new UnsupportedOperationException();
+  }
+
+  public ShardResolutionStrategy getShardResolutionStrategy() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyFactoryDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyFactoryDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/ShardStrategyFactoryDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy;
+
+import org.hibernate.shards.ShardId;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardStrategyFactoryDefaultMock implements ShardStrategyFactory {
+
+  public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardAccessStrategyTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardAccessStrategyTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardAccessStrategyTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import junit.framework.TestCase;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ParallelShardAccessStrategyTest extends TestCase {
+
+  public void testCtor() {
+    try {
+      new ParallelShardAccessStrategy(null);
+      fail("expected npe");
+    } catch (NullPointerException npe) {
+      // good
+    }
+  }
+
+  
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardOperationCallableTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardOperationCallableTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ParallelShardOperationCallableTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardDefaultMock;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.ShardOperationDefaultMock;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+import org.hibernate.shards.strategy.exit.ExitStrategyDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.Sets;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Callable;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class ParallelShardOperationCallableTest extends TestCase {
+
+  public void testCountDown() throws Exception {
+    int latchSize = 5;
+    CountDownLatch startLatch = new CountDownLatch(0);
+    CountDownLatch latch = new CountDownLatch(latchSize);
+    final boolean[] addResultResult = {false};
+    ExitStrategy<Void> strat = new ExitStrategyDefaultMock<Void>() {
+      @Override      
+      public boolean addResult(Void result, Shard shard) {
+        return addResultResult[0];
+      }
+    };
+    ShardOperation<Void> operation = new ShardOperationDefaultMock<Void>() {
+      @Override
+      public Void execute(Shard shard) {
+        return null;
+      }
+
+      @Override
+      public String getOperationName() {
+        return "yam";
+      }
+    };
+    Shard shard = new ShardDefaultMock() {
+      @Override
+      public String toString() {
+        return "yam";
+      }
+
+      @Override
+      public Set<ShardId> getShardIds() {
+        return Sets.newHashSet(new ShardId(0));
+      }
+    };
+    List<StartAwareFutureTask> futureTasks = Lists.newArrayList();
+    ParallelShardOperationCallable<Void> callable = new ParallelShardOperationCallable<Void>(
+        startLatch,
+        latch,
+        strat,
+        operation,
+        shard,
+        futureTasks);
+
+    callable.call();
+    // addResult returns false so latch is only decremented by 1
+    assertEquals(latchSize - 1, latch.getCount());
+    // addResult returns false so latch is only decremented by 1
+    callable.call();
+    assertEquals(latchSize - 2, latch.getCount());
+
+    // now addResult returns true
+    addResultResult[0] = true;
+    Callable<Void> anotherCallable = new Callable<Void>() {
+      public Void call() {
+        return null;
+      }
+    };
+    StartAwareFutureTask ft = new StartAwareFutureTask(anotherCallable, 0) {
+      @Override
+      public boolean cancel(boolean mayInterruptIfRunning) {
+        return false;
+      }
+    };
+    futureTasks.add(ft);
+    callable.call();
+    // cancelling the 1 task returns false, so latch is only decremented by 1
+    assertEquals(latchSize - 3, latch.getCount());
+
+    // add a second task that returns true when cancelled
+    ft = new StartAwareFutureTask(anotherCallable, 0) {
+      @Override
+      public boolean cancel(boolean mayInterruptIfRunning) {
+        return true;
+      }
+    };
+    futureTasks.add(ft);
+    callable.call();
+    // 1 decrement for myself and 1 for the task that returned true when cancelled
+    assertEquals(latchSize - 5, latch.getCount());
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ShardAccessStrategyDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ShardAccessStrategyDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/ShardAccessStrategyDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardOperation;
+import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
+import org.hibernate.shards.strategy.exit.ExitStrategy;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardAccessStrategyDefaultMock implements ShardAccessStrategy {
+
+  public <T> T apply(List<Shard> shards, ShardOperation<T> operation,
+      ExitStrategy<T> exitStrategy, ExitOperationsCollector exitOperationsCollector) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/StartAwareFutureTaskTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/StartAwareFutureTaskTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/access/StartAwareFutureTaskTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,143 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.access;
+
+import junit.framework.TestCase;
+
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.Callable;
+
+/**
+ * @author maxr at google.com (Max Ross)
+ */
+public class StartAwareFutureTaskTest extends TestCase {
+
+  /**
+   * This test demonstrates that cancelling an in progress
+   * FutureTask returns true.
+   */
+  public void testCancelBehavior() {
+    Runnable r = new Runnable() {
+      public synchronized void run() {
+        try {
+          wait();
+        } catch (InterruptedException e) {
+          fail("unexpected interrupted exception");
+        }
+      }
+    };
+
+    FutureTask<Object> ft = new FutureTask<Object>(r, null);
+    Thread t = new Thread(ft);
+    try {
+      t.start();
+      assertThreadStateEquals(Thread.State.WAITING, t);
+      assertTrue(ft.cancel(false));
+      assertTrue(ft.isCancelled());
+    } finally {
+      synchronized(t) {
+        t.notify();
+      }
+    }
+  }
+
+  /**
+   * This test demonstrates that cancelling an in progress
+   * StartAwareFutureTask returns false.
+   */
+  public void testCustomCancelBehavior() {
+    Callable<Void> c = new Callable<Void>() {
+      public synchronized Void call() throws Exception {
+        try {
+          wait();
+        } catch (InterruptedException e) {
+          fail("unexpected interrupted exception");
+        }
+        return null;
+      }
+    };
+
+    StartAwareFutureTask ft = new StartAwareFutureTask(c, 0);
+    Thread t = new Thread(ft);
+    try {
+      t.start();
+      assertThreadStateEquals(Thread.State.WAITING, t);
+      assertFalse(ft.cancel(false));
+      assertFalse(ft.isCancelled());
+    } finally {
+      synchronized(t) {
+        t.notify();
+      }
+    }
+  }
+
+  public void testCustomCancelBehaviorWhenRunning() {
+    Callable<Void> c = new Callable<Void>() {
+      public Void call() {
+        throw new UnsupportedOperationException();
+      }
+    };
+
+    StartAwareFutureTask ft = new StartAwareFutureTask(c, 0);
+    assertFalse(ft.cancelled);
+    assertFalse(ft.runCalled);
+    assertTrue(ft.cancel(false));
+    assertTrue(ft.cancelled);
+    assertFalse(ft.runCalled);
+    ft.run();
+    assertFalse(ft.runCalled);
+  }
+
+  public void testCustomCancelBehaviorWhenCancelling() {
+    Callable<Void> c = new Callable<Void>() {
+      public Void call() {
+        return null;
+      }
+    };
+
+    StartAwareFutureTask ft = new StartAwareFutureTask(c, 0) {
+      @Override
+      boolean superCancel(boolean mayInterruptIfRunning) {
+        throw new UnsupportedOperationException();
+      }
+    };
+    assertFalse(ft.cancelled);
+    assertFalse(ft.runCalled);
+    ft.run();
+    assertFalse(ft.cancelled);
+    assertTrue(ft.runCalled);
+    ft.cancel(false);
+    assertFalse(ft.cancelled);
+  }
+
+  private void assertThreadStateEquals(Thread.State expectedState, Thread t) {
+    long startTime = System.currentTimeMillis();
+    long maxElapsed = 500;
+    while(t.getState() != expectedState) {
+      if(System.currentTimeMillis() - startTime >= maxElapsed) {
+        fail("Thread never arrived in expected state " + expectedState);
+      }
+      try {
+        Thread.sleep(5);
+      } catch (InterruptedException e) {
+
+      }
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,156 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.defaultmock.EntityPersisterDefaultMock;
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.defaultmock.ClassMetadataDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.StringUtil;
+
+import junit.framework.TestCase;
+
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.hibernate.MappingException;
+import org.hibernate.criterion.AvgProjection;
+import org.hibernate.criterion.Projections;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.persister.entity.EntityPersister;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.util.List;
+
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class AggregateExitOperationTest extends TestCase {
+
+  private List<Object> data;
+
+  private class MyInt implements Comparable {
+    private final Integer i;
+
+    public MyInt(int i) {
+      this.i = i;
+    }
+
+    public Number getValue() {
+      return i;
+    }
+
+    public int compareTo(Object o) {
+      MyInt i = (MyInt) o;
+      return (Integer)this.getValue() - (Integer)i.getValue();
+    }
+  }
+
+  protected void setUp() throws Exception {
+    super.setUp();
+    data = Lists.<Object>newArrayList();
+    for(int i=0; i<6; i++) {
+      if (i == 4) {
+        data.add(null);
+      } else {
+        data.add(new MyInt(i));
+      }
+    }
+  }
+
+  public void testCtor() throws Exception {
+    try {
+      new AggregateExitOperation(new AvgProjection("foo"), new SessionFactoryMock());
+      fail();
+    } catch (IllegalArgumentException e) {
+      // good
+    }
+    try {
+      new AggregateExitOperation(new AvgProjection("foo"), new SessionFactoryDefaultMock());
+      fail();
+    } catch (IllegalArgumentException e) {
+      // good
+    }
+    new AggregateExitOperation(Projections.max("foo"), new SessionFactoryDefaultMock());
+    new AggregateExitOperation(Projections.min("foo"), new SessionFactoryDefaultMock());
+    new AggregateExitOperation(Projections.sum("foo"), new SessionFactoryDefaultMock());
+  }
+
+  public void testSum() throws Exception {
+    AggregateExitOperation exitOp = new AggregateExitOperation(Projections.sum("value"), new SessionFactoryMock());
+
+    List<Object> result = exitOp.apply(data);
+    assertEquals(new BigDecimal(11.0), (BigDecimal)result.get(0));
+  }
+
+  public void testMax() throws Exception {
+    AggregateExitOperation exitOp = new AggregateExitOperation(Projections.max("value"), new SessionFactoryMock());
+
+    List<Object> result = exitOp.apply(data);
+    assertEquals(5, ((MyInt)result.get(0)).getValue());
+  }
+
+  public void testMin() throws Exception {
+    AggregateExitOperation exitOp = new AggregateExitOperation(Projections.min("value"), new SessionFactoryMock());
+
+    List<Object> result = exitOp.apply(data);
+    assertEquals(0, ((MyInt)result.get(0)).getValue());
+  }
+
+  static class SessionFactoryMock extends SessionFactoryDefaultMock {
+
+    public ClassMetadata getClassMetadata(Class persistentClass)
+        throws HibernateException {
+      return new ClassMetadataMock();
+    }
+
+    public EntityPersister getEntityPersister(String entityName)
+        throws MappingException {
+      return new EntityPersisterMock();
+    }
+  }
+
+  static class ClassMetadataMock extends ClassMetadataDefaultMock {
+
+    public String getEntityName() {
+      return "";
+    }
+  }
+
+  static class EntityPersisterMock extends EntityPersisterDefaultMock {
+
+    public Object getPropertyValue(Object object, String propertyName,
+        EntityMode entityMode) throws HibernateException {
+      Class clazz = object.getClass();
+      propertyName = StringUtil.capitalize(propertyName);
+      try {
+        Method m = clazz.getMethod("get" + propertyName);
+        return m.invoke(object);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      } catch (InvocationTargetException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitOperationUtilsTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitOperationUtilsTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitOperationUtilsTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,64 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import junit.framework.TestCase;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ExitOperationUtilsTest extends TestCase {
+
+    private class MyInt {
+      private final Integer i;
+
+      private final String name;
+
+      private MyInt innerMyInt;
+
+      public MyInt(int i, String name) {
+        this.i = i;
+        this.name = name;
+      }
+
+      public MyInt getInnerMyInt() {
+        return innerMyInt;
+      }
+
+      public void setInnerMyInt(MyInt innerMyInt) {
+        this.innerMyInt = innerMyInt;
+      }
+
+      public Number getValue() {
+        return i;
+      }
+
+      public String getName() {
+        return name;
+      }
+
+    }
+
+  public void testGetPropertyValue() throws Exception {
+    MyInt myInt = new MyInt(1,"one");
+    myInt.setInnerMyInt(new MyInt(5, "five"));
+    assertEquals(5, ExitOperationUtils.getPropertyValue(myInt,"innerMyInt.value"));
+    assertEquals("five", ExitOperationUtils.getPropertyValue(myInt,"innerMyInt.name"));
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitStrategyDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitStrategyDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ExitStrategyDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.Shard;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ExitStrategyDefaultMock<T> implements ExitStrategy<T> {
+
+  public boolean addResult(T result, Shard shard) {
+    throw new UnsupportedOperationException();
+  }
+
+  public T compileResults(ExitOperationsCollector exitOperationsCollector) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class FirstResultExitOperationTest extends TestCase {
+
+  public void testApply() {
+    FirstResultExitOperation exitOp = new FirstResultExitOperation(1);
+
+    List<Object> list = Lists.<Object>newArrayList(1, 2, null, 3, 4, 5);
+
+    List<Object> objects = exitOp.apply(list);
+    assertEquals(4, objects.size());
+    assertNoNullElements(objects);
+    assertEquals(Lists.newArrayList(2, 3, 4, 5), objects);
+    exitOp = new FirstResultExitOperation(2);
+
+    list = Lists.<Object>newArrayList(1, 2, null, 3, 4, 5);
+
+    objects = exitOp.apply(list);
+    assertEquals(3, objects.size());
+    assertNoNullElements(objects);
+    assertEquals(Lists.newArrayList(3, 4, 5), objects);
+  }
+
+  public void testApplyWhenNoResults() {
+    FirstResultExitOperation exitOp = new FirstResultExitOperation(9);
+
+    List<Object> list = Lists.newArrayList();
+
+    List<Object> objects = exitOp.apply(list);
+    assertTrue(objects.isEmpty());
+
+    list = Lists.newArrayList(null, null, null);
+
+    objects = exitOp.apply(list);
+    assertTrue(objects.isEmpty());
+  }
+
+  public void testApplyWhenFirstResultIsTooBig() {
+    FirstResultExitOperation exitOp = new FirstResultExitOperation(9);
+
+    List<Object> list = Lists.<Object>newArrayList(1, 2, null, 3, 4, 5);
+
+    List<Object> objects = exitOp.apply(list);
+    assertTrue(objects.isEmpty());
+
+    // edge case
+    exitOp = new FirstResultExitOperation(list.size());
+    objects = exitOp.apply(list);
+    assertTrue(objects.isEmpty());
+  }
+
+  private void assertNoNullElements(List<Object> objects) {
+    for(Object obj : objects) {
+      assertTrue(obj != null);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/MaxResultExitOperationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/MaxResultExitOperationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/MaxResultExitOperationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class MaxResultExitOperationTest extends TestCase {
+
+  public void testApply() {
+    MaxResultsExitOperation exitOp = new MaxResultsExitOperation(3);
+
+    List<Object> list = Lists.<Object>newArrayList(1, 2, null, 3, 4, 5);
+
+    List<Object> objects = exitOp.apply(list);
+    assertEquals(3, objects.size());
+    assertNoNullElements(objects);
+    assertEquals(Lists.newArrayList(1, 2, 3), objects);
+  }
+
+  public void testApplyWithFewerElementsThanMaxResults() {
+    MaxResultsExitOperation exitOp = new MaxResultsExitOperation(8);
+    List<Object> list = Lists.<Object>newArrayList(1, 2, null, 3, 4, 5);
+    List<Object> objects = exitOp.apply(list);
+    assertEquals(5, objects.size());
+    assertNoNullElements(objects);
+    assertEquals(Lists.newArrayList(1, 2, 3, 4, 5), objects);
+  }
+
+  private void assertNoNullElements(List<Object> objects) {
+    for(Object obj : objects) {
+      assertTrue(obj != null);
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,173 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.defaultmock.ClassMetadataDefaultMock;
+import org.hibernate.shards.defaultmock.EntityPersisterDefaultMock;
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.util.StringUtil;
+
+import junit.framework.TestCase;
+
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.hibernate.MappingException;
+import org.hibernate.criterion.Order;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.persister.entity.EntityPersister;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class OrderExitOperationTest extends TestCase {
+
+  private List<Object> data;
+  private ArrayList<Object> shuffledList;
+  private List<Object> nonNullData;
+
+  private class MyInt {
+    private final Integer i;
+
+    private final String name;
+
+    private MyInt innerMyInt;
+
+    public MyInt(int i, String name) {
+      this.i = i;
+      this.name = name;
+    }
+
+    public MyInt getInnerMyInt() {
+      return innerMyInt;
+    }
+
+    public void setInnerMyInt(MyInt innerMyInt) {
+      this.innerMyInt = innerMyInt;
+    }
+
+    public Number getValue() {
+      return i;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public boolean equals(Object obj) {
+      MyInt myInt = (MyInt) obj;
+      return
+          this.getName().equals(myInt.getName()) &&
+          this.getValue().equals(myInt.getValue());
+    }
+  }
+
+  protected void setUp() throws Exception {
+    super.setUp();
+    String[] names = {"tomislav", "max", "maulik", "gut", "null", "bomb"};
+    data = Lists.newArrayList();
+    for(int i=0; i<6; i++) {
+      if (i == 4) {
+        data.add(null);
+      } else {
+        data.add(new MyInt(i, names[i]));
+      }
+    }
+
+    nonNullData = ExitOperationUtils.getNonNullList(data);
+
+    shuffledList = Lists.newArrayList(data);
+    Collections.shuffle(shuffledList);
+  }
+
+  public void testApply() throws Exception {
+    Order order = Order.asc("value");
+    OrderExitOperation oeo = new OrderExitOperation(order, new SessionFactoryMock());
+    List unShuffledList = oeo.apply(shuffledList);
+
+    assertTrue(nonNullData.equals(unShuffledList));
+  }
+
+  public void testMultipleOrderings() throws Exception {
+    Order orderValue = Order.asc("value");
+    Order orderName = Order.desc("name");
+
+    OrderExitOperation oeoValue = new OrderExitOperation(orderValue, new SessionFactoryMock());
+    OrderExitOperation oeoName = new OrderExitOperation(orderName, new SessionFactoryMock());
+
+    List<MyInt> answer =
+        Lists.newArrayList(
+            new MyInt(0, "tomislav"),
+            new MyInt(1, "max"),
+            new MyInt(2, "maulik"),
+            new MyInt(3, "gut"),
+            new MyInt(5, "bomb"));
+    List unShuffledList = oeoName.apply(oeoValue.apply(shuffledList));
+
+
+    assertEquals(answer, unShuffledList);
+
+  }
+
+  static class SessionFactoryMock extends SessionFactoryDefaultMock {
+
+    public ClassMetadata getClassMetadata(Class persistentClass)
+        throws HibernateException {
+      return new ClassMetadataMock();
+    }
+
+    public EntityPersister getEntityPersister(String entityName)
+        throws MappingException {
+      return new EntityPersisterMock();
+    }
+  }
+
+  static class ClassMetadataMock extends ClassMetadataDefaultMock {
+
+    public String getEntityName() {
+      return "";
+    }
+  }
+
+  static class EntityPersisterMock extends EntityPersisterDefaultMock {
+
+    public Object getPropertyValue(Object object, String propertyName,
+        EntityMode entityMode) throws HibernateException {
+      Class clazz = object.getClass();
+      propertyName = StringUtil.capitalize(propertyName);
+      try {
+        Method m = clazz.getMethod("get" + propertyName);
+        return m.invoke(object);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      } catch (InvocationTargetException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactoryTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactoryTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactoryTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.defaultmock.EntityPersisterDefaultMock;
+import org.hibernate.shards.defaultmock.SessionFactoryDefaultMock;
+import org.hibernate.shards.util.StringUtil;
+
+import junit.framework.TestCase;
+
+import org.hibernate.EntityMode;
+import org.hibernate.HibernateException;
+import org.hibernate.MappingException;
+import org.hibernate.criterion.Projections;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.persister.entity.EntityPersister;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class ProjectionExitOperationFactoryTest extends TestCase {
+
+  public void testReturnedOperations() throws Exception {
+    ProjectionExitOperationFactory factory = ProjectionExitOperationFactory.getFactory();
+
+    assertTrue(factory.getProjectionExitOperation(Projections.rowCount(), new SessionFactoryMock()) instanceof RowCountExitOperation);
+    assertTrue(factory.getProjectionExitOperation(Projections.max("foo"), new SessionFactoryMock()) instanceof AggregateExitOperation);
+    assertTrue(factory.getProjectionExitOperation(Projections.min("foo"), new SessionFactoryMock()) instanceof AggregateExitOperation);
+    assertTrue(factory.getProjectionExitOperation(Projections.sum("foo"), new SessionFactoryMock()) instanceof AggregateExitOperation);
+    try {
+      factory.getProjectionExitOperation(Projections.avg("foo"), new SessionFactoryMock());
+      fail("example of one that we don't yet support");
+    } catch (IllegalArgumentException e) {
+      // good
+    }
+  }
+
+  static class SessionFactoryMock extends SessionFactoryDefaultMock {
+
+    public ClassMetadata getClassMetadata(Class persistentClass)
+        throws HibernateException {
+      return null;
+    }
+
+    public EntityPersister getEntityPersister(String entityName)
+        throws MappingException {
+      return new EntityPersisterMock();
+    }
+  }
+
+  static class EntityPersisterMock extends EntityPersisterDefaultMock {
+
+    public Object getPropertyValue(Object object, String propertyName,
+        EntityMode entityMode) throws HibernateException {
+      Class clazz = object.getClass();
+      propertyName = StringUtil.capitalize(propertyName);
+      try {
+        Method m = clazz.getMethod("get" + propertyName);
+        return m.invoke(object);
+      } catch (NoSuchMethodException e) {
+        throw new RuntimeException(e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      } catch (InvocationTargetException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/RowCountExitOperationTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/RowCountExitOperationTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/exit/RowCountExitOperationTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.exit;
+
+import org.hibernate.shards.util.Lists;
+
+import junit.framework.TestCase;
+
+import org.hibernate.criterion.Projections;
+
+import java.util.List;
+
+/**
+ * @author maulik at google.com (Maulik Shah)
+ */
+public class RowCountExitOperationTest extends TestCase {
+  public void testCtor() throws Exception {
+    try {
+      new RowCountExitOperation(Projections.avg("foo"));
+      fail();
+    } catch (IllegalStateException e) {
+      //good
+    }
+  }
+
+  public void testApplyCount() throws Exception {
+    RowCountExitOperation exitOp = new RowCountExitOperation(Projections.rowCount());
+
+    List<Object> list = Lists.<Object>newArrayList(1,2,null,3);
+    assertEquals(3, (int)(Integer)exitOp.apply(list).get(0));
+  }
+
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDataDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDataDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDataDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.resolution;
+
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
+
+import java.io.Serializable;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardResolutionStrategyDataDefaultMock implements ShardResolutionStrategyData {
+
+  public String getEntityName() {
+    throw new UnsupportedOperationException();
+  }
+
+  public Serializable getId() {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/resolution/ShardResolutionStrategyDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.resolution;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.strategy.selection.ShardResolutionStrategyData;
+
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardResolutionStrategyDefaultMock implements ShardResolutionStrategy {
+
+  public List<ShardId> selectShardIdsFromShardResolutionStrategyData(
+      ShardResolutionStrategyData shardResolutionStrategyData) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategyTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategyTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/LoadBalancedShardSelectionStrategyTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,46 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.loadbalance.ShardLoadBalancer;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class LoadBalancedShardSelectionStrategyTest extends TestCase {
+
+  public void testSelectShardForNewObject() {
+    final List<ShardId> shardIds = Collections.emptyList();
+    final ShardId shardId = new ShardId(1);
+    ShardLoadBalancer balancer = new ShardLoadBalancer() {
+      public ShardId getNextShardId() {
+        return shardId;
+      }
+    };
+    LoadBalancedShardSelectionStrategy strategy = new LoadBalancedShardSelectionStrategy(balancer);
+    assertSame(shardId, strategy.selectShardIdForNewObject(null));
+    assertSame(shardId, strategy.selectShardIdForNewObject(null));
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/ShardSelectionStrategyDefaultMock.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/ShardSelectionStrategyDefaultMock.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/strategy/selection/ShardSelectionStrategyDefaultMock.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.strategy.selection;
+
+import org.hibernate.shards.ShardId;
+
+/**
+ * @author Max Ross <maxr at google.com>
+ */
+public class ShardSelectionStrategyDefaultMock implements ShardSelectionStrategy {
+
+  public ShardId selectShardIdForNewObject(Object obj) {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/transaction/ShardedTransactionImplTest.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/transaction/ShardedTransactionImplTest.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/transaction/ShardedTransactionImplTest.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,261 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.transaction;
+
+import org.hibernate.shards.defaultmock.SessionDefaultMock;
+import org.hibernate.shards.Shard;
+import org.hibernate.shards.ShardDefaultMock;
+import org.hibernate.shards.ShardedTransactionDefaultMock;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.shards.engine.ShardedSessionImplementorDefaultMock;
+
+import junit.framework.TestCase;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Transaction;
+import org.hibernate.TransactionException;
+import org.hibernate.classic.Session;
+
+import java.util.List;
+
+import javax.transaction.Synchronization;
+
+/**
+ * @author tomislav at google.com (Tomislav Nad)
+ */
+public class ShardedTransactionImplTest extends TestCase {
+
+  private ShardedTransactionImpl sti;
+  private TransactionStub transaction1;
+
+  private class TransactionStub extends ShardedTransactionDefaultMock {
+    public boolean fail = false;
+    public boolean wasCommitted = false;
+
+    @Override
+    public void setupTransaction(org.hibernate.Session session) {}
+
+    @Override
+    public void begin() throws HibernateException {
+      if (fail) {
+        throw new TransactionException("failed");
+      }
+    }
+
+    @Override
+    public void commit() throws HibernateException {
+      if (fail) {
+        throw new TransactionException("failed");
+      }
+      wasCommitted = true;
+    }
+
+    @Override
+    public void rollback() throws HibernateException {
+      if (fail) {
+        throw new TransactionException("failed");
+      }
+    }
+
+    @Override
+    public boolean wasCommitted() throws HibernateException {
+      return wasCommitted;
+    }
+
+    @Override
+    public boolean isActive() throws HibernateException {
+      return true;
+    }
+
+    @Override
+    public void registerSynchronization(Synchronization synchronization)
+        throws HibernateException {}
+
+    @Override
+    public void setTimeout(int seconds) {}
+  }
+
+  private static class MockSession extends SessionDefaultMock {
+    private Transaction transaction;
+
+    MockSession(Transaction t) {
+      transaction = t;
+    }
+
+    @Override
+    public Transaction getTransaction() {
+      return transaction;
+    }
+  }
+
+  private static class MockShard extends ShardDefaultMock {
+    private Session session;
+
+    MockShard(Session s) {
+      session = s;
+    }
+
+    @Override
+    public Session getSession() {
+      return session;
+    }
+  }
+
+  private static class MockShardedSessionImplementor extends ShardedSessionImplementorDefaultMock {
+    private List<Shard> shards;
+
+    MockShardedSessionImplementor(List<Shard> shards) {
+      this.shards = shards;
+    }
+
+    @Override
+    public List<Shard> getShards() {
+      return shards;
+    }
+  }
+
+  @Override
+  protected void setUp() {
+    TransactionStub transaction1
+        = new TransactionStub();
+    this.transaction1 = new TransactionStub();
+    List<Shard> shards = Lists.newArrayList();
+    shards.add(new MockShard(new MockSession(transaction1)));
+    shards.add(new MockShard(new MockSession(this.transaction1)));
+    sti = new ShardedTransactionImpl(new MockShardedSessionImplementor(shards));
+  }
+
+  public void testBeginSimple() {
+    sti.begin();
+    assertTrue(sti.isActive());
+    assertFalse(sti.wasCommitted());
+    assertFalse(sti.wasRolledBack());
+
+    // test double begin
+    sti.begin();
+    assertTrue(sti.isActive());
+    assertFalse(sti.wasCommitted());
+    assertFalse(sti.wasRolledBack());
+
+    // test begin after commit failed
+    transaction1.fail = true;
+    try {
+      sti.commit();
+    } catch (HibernateException he) {}
+    transaction1.fail = false;
+    try {
+      sti.begin();
+      fail();
+    } catch (HibernateException he) {
+      // good
+    }
+  }
+
+  public void testBeginWithOneFailedTransaction() {
+    transaction1.fail = true;
+    try {
+      sti.begin();
+      fail();
+    } catch (HibernateException he) {
+      assertFalse(sti.isActive());
+    }
+
+    transaction1.fail = false;
+    sti.begin();
+    assertTrue(sti.isActive());
+    assertFalse(sti.wasCommitted());
+    assertFalse(sti.wasRolledBack());
+  }
+
+  public void testCommitSimple() {
+    try {
+      sti.commit();
+      fail();
+    } catch (HibernateException he) {
+      // good
+    }
+
+    sti.begin();
+    sti.commit();
+    assertTrue(sti.wasCommitted());
+    assertFalse(sti.isActive());
+  }
+
+  public void testCommitWithOneFailedTransaction() {
+    sti.begin();
+    transaction1.fail = true;
+    try {
+      sti.commit();
+      fail();
+    } catch (HibernateException he) {
+      assertFalse(sti.wasCommitted());
+    }
+  }
+
+  public void testRollbackSimple() {
+    try {
+      sti.rollback();
+      fail();
+    } catch (HibernateException hel) {
+      // good
+    }
+
+    sti.begin();
+    sti.rollback();
+    assertTrue(sti.wasRolledBack());
+
+    sti.commit();
+    try {
+      sti.rollback();
+      fail();
+    } catch (HibernateException he) {
+      // good
+    }
+
+    sti.begin();
+    transaction1.fail = true;
+    try {
+      sti.commit();
+    } catch (HibernateException he) {
+      sti.rollback();
+      assertTrue(sti.wasRolledBack());
+    }
+  }
+
+  public void testRollbackWithOneFailedTransaction() {
+    sti.begin();
+    transaction1.fail = true;
+    try {
+      sti.rollback();
+    } catch (HibernateException he) {
+      assertFalse(sti.wasRolledBack());
+    }
+  }
+
+  public void testMultipleIterations() {
+    sti.begin();
+    sti.commit();
+
+    sti.begin();
+    assertTrue(sti.isActive());
+    assertFalse(sti.wasCommitted());
+    sti.commit();
+    assertTrue(sti.wasCommitted());
+  }
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcStrategy.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcStrategy.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcStrategy.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,26 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public interface JdbcStrategy {
+  void extractData(ResultSet rs) throws SQLException;
+}

Added: trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcUtil.java
===================================================================
--- trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcUtil.java	                        (rev 0)
+++ trunk/HibernateExt/shards/src/test/org/hibernate/shards/util/JdbcUtil.java	2007-03-17 16:31:42 UTC (rev 11294)
@@ -0,0 +1,133 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.hibernate.shards.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * Helper methods for Jdbc
+ *
+ * @author Max Ross <maxr at google.com>
+ */
+public class JdbcUtil {
+
+  private static final Log LOG = LogFactory.getLog(JdbcUtil.class);
+
+  public static int executeUpdate(
+      Connection conn,
+      String query,
+      boolean closeConnection) throws SQLException {
+    Statement statement = null;
+    try {
+      statement = conn.createStatement();
+      return statement.executeUpdate(query);
+    } finally {
+      if (closeConnection) {
+        closeAllResources(null, statement, conn);
+      } else {
+        closeAllResources(null, statement, null);
+      }
+    }
+  }
+
+  public static void executeJdbcQuery(
+      Connection conn,
+      String query,
+      JdbcStrategy jdbcStrategy,
+      boolean closeConnection) throws SQLException {
+    Statement statement = null;
+    ResultSet rs = null;
+    try {
+      statement = conn.createStatement();
+      rs = statement.executeQuery(query);
+      while (rs.next()) {
+        jdbcStrategy.extractData(rs);
+      }
+    } finally {
+      if (closeConnection) {
+        closeAllResources(rs, statement, conn);
+      } else {
+        closeAllResources(rs, statement, null);
+      }
+    }
+  }
+
+
+  public static void executeJdbcQuery(Connection conn, String query,
+      JdbcStrategy jdbcStrategy)
+      throws SQLException {
+    executeJdbcQuery(conn, query, jdbcStrategy, true);
+  }
+
+  public static void executePreparedStatementQuery(Connection conn,
+      PreparedStatement stmt, JdbcStrategy strategy, boolean closeConnection)
+      throws SQLException {
+    ResultSet rs = null;
+    try {
+      rs = stmt.executeQuery();
+      while (rs.next()) {
+        strategy.extractData(rs);
+      }
+    } finally {
+      if (closeConnection) {
+        closeAllResources(rs, stmt, conn);
+      } else {
+        closeAllResources(rs, stmt, null);
+      }
+    }
+  }
+
+  public static void executePreparedStatementQuery(Connection conn,
+      PreparedStatement stmt, JdbcStrategy strategy)
+      throws SQLException {
+    executePreparedStatementQuery(conn, stmt, strategy, true);
+  }
+
+  public static void closeAllResources(ResultSet rs, Statement statement,
+      Connection conn) {
+    if (rs != null) {
+      try {
+        rs.close();
+      } catch (Throwable t) {
+        LOG.error("Error closing result set.", t);
+      }
+    }
+    if (statement != null) {
+      try {
+        statement.close();
+      } catch (Throwable t) {
+        LOG.error("Error closing statement.", t);
+      }
+    }
+    if (conn != null) {
+      try {
+        conn.close();
+      } catch (Throwable t) {
+        LOG.error("Error closing connection.", t);
+      }
+    }
+  }
+}




More information about the hibernate-commits mailing list